From a31bbff89a96e07dde11fabe267312ffd8b225c0 Mon Sep 17 00:00:00 2001 From: perazz Date: Mon, 21 Oct 2024 16:43:53 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20=20@=20d9205?= =?UTF-8?q?3e945c2b18b6422c77aea38bb79414a2821=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- interface/add_table.html | 8 +- interface/build_progress_t.html | 2 +- interface/debug.html | 6 +- interface/fnv_1a.html | 6 +- interface/get_value.html | 20 +- interface/len_trim.html | 4 +- interface/new_version.html | 12 +- interface/operator(.in.).html | 2 +- interface/operator(==).html | 10 +- interface/resize.html | 24 +- interface/resize~2.html | 20 +- interface/resize~3.html | 28 +- interface/resolve_metapackages.html | 10 +- interface/set_string.html | 14 +- interface/set_value.html | 20 +- interface/str.html | 8 +- interface/str_ends_with.html | 8 +- interface/string_t.html | 4 +- lists/files.html | 2 +- lists/modules.html | 2 +- lists/procedures.html | 44 +- lists/types.html | 2 +- module/fpm.html | 40 +- module/fpm_backend.html | 16 +- module/fpm_backend_console.html | 2 +- module/fpm_backend_output.html | 10 +- module/fpm_cmd_export.html | 10 +- module/fpm_cmd_install.html | 16 +- module/fpm_cmd_new.html | 8 +- module/fpm_cmd_publish.html | 18 +- module/fpm_cmd_update.html | 6 +- module/fpm_command_line.html | 122 +-- module/fpm_compiler.html | 198 ++--- module/fpm_dependency.html | 80 +- module/fpm_downloader.html | 2 +- module/fpm_environment.html | 14 +- module/fpm_error.html | 26 +- module/fpm_filesystem.html | 90 +-- module/fpm_git.html | 82 +- module/fpm_installer.html | 20 +- module/fpm_manifest.html | 32 +- module/fpm_manifest_build.html | 34 +- module/fpm_manifest_dependency.html | 66 +- module/fpm_manifest_example.html | 24 +- module/fpm_manifest_executable.html | 28 +- module/fpm_manifest_fortran.html | 28 +- module/fpm_manifest_install.html | 22 +- module/fpm_manifest_library.html | 28 +- module/fpm_manifest_metapackages.html | 24 +- module/fpm_manifest_package.html | 60 +- module/fpm_manifest_preprocess.html | 36 +- module/fpm_manifest_profile.html | 136 ++-- module/fpm_manifest_test.html | 24 +- module/fpm_meta.html | 48 +- module/fpm_model.html | 130 ++- module/fpm_os.html | 26 +- module/fpm_pkg_config.html | 22 +- module/fpm_release.html | 4 +- module/fpm_settings.html | 10 +- module/fpm_source_parsing.html | 18 +- module/fpm_sources.html | 22 +- module/fpm_strings.html | 76 +- module/fpm_targets.html | 58 +- module/fpm_toml.html | 96 +-- module/fpm_versioning.html | 20 +- page/Contributing.html | 2 +- page/License.html | 2 +- page/Manifest.html | 2 +- page/Packaging.html | 2 +- page/index.html | 2 +- proc/add_dependency.html | 4 +- proc/add_executable_sources.html | 8 +- proc/add_sources_from_dir.html | 10 +- proc/add_target.html | 12 +- proc/ar_is_same.html | 6 +- proc/assert_pkg_config.html | 2 +- proc/bad_name_error.html | 6 +- proc/basename.html | 4 +- proc/build_model.html | 10 +- proc/build_package.html | 6 +- proc/canon_path.html | 4 +- proc/change_directory.html | 6 +- proc/check_and_read_pkg_data.html | 6 +- proc/check_compiler.html | 4 +- proc/check_fortran_source_runs.html | 12 +- proc/check_keys.html | 8 +- proc/check_modules_for_duplicates.html | 4 +- proc/checkout.html | 14 +- proc/cmd_build.html | 4 +- proc/cmd_clean.html | 4 +- proc/cmd_export.html | 4 +- proc/cmd_install.html | 4 +- proc/cmd_new.html | 4 +- proc/cmd_publish.html | 6 +- proc/cmd_run.html | 6 +- proc/cmd_update.html | 4 +- proc/compile_c.html | 10 +- proc/compile_cpp.html | 10 +- proc/compile_fortran.html | 10 +- proc/compiler_dump.html | 12 +- proc/compiler_is_same.html | 6 +- proc/compiler_load.html | 8 +- proc/compiler_name.html | 6 +- proc/convert_to_absolute_path.html | 6 +- proc/debug_archiver.html | 4 +- proc/debug_compiler.html | 4 +- proc/default_example.html | 6 +- proc/default_executable.html | 6 +- proc/default_library.html | 4 +- proc/default_test.html | 6 +- proc/delete_env.html | 6 +- proc/delete_file.html | 4 +- proc/dependency_destroy.html | 4 +- proc/descriptor_name.html | 4 +- proc/destroy_dependency_node.html | 4 +- proc/dilate.html | 2 +- proc/dirname.html | 6 +- ...ump_to_toml~3.html => dump_to_toml~4.html} | 14 +- ...ump_to_toml~8.html => dump_to_toml~9.html} | 10 +- proc/enumerate_libraries.html | 10 +- proc/execute_and_read_output.html | 10 +- proc/exists.html | 6 +- proc/f_string.html | 2 +- proc/fatal_error.html | 6 +- proc/file_not_found_error.html | 4 +- proc/file_parse_error.html | 6 +- proc/file_scope_dump.html | 8 +- proc/file_scope_load.html | 8 +- proc/file_scope_same.html | 6 +- proc/fileclose.html | 4 +- proc/fileopen.html | 6 +- proc/filewrite.html | 4 +- proc/filter_executable_targets.html | 6 +- proc/filter_library_targets.html | 6 +- proc/filter_modules.html | 6 +- proc/find_profile.html | 12 +- proc/fpm_scope_name.html | 6 +- proc/fpm_stop.html | 4 +- proc/fpm_target_name.html | 2 +- proc/fpm_unit_name.html | 270 +++++++ proc/fpm_version.html | 2 +- proc/get_absolute_path.html | 6 +- proc/get_absolute_path_by_cd.html | 6 +- proc/get_command_arguments_quoted.html | 4 +- proc/get_command_line_settings.html | 2 +- proc/get_compiler_id.html | 20 +- proc/get_current_directory.html | 6 +- proc/get_debug_compile_flags.html | 4 +- proc/get_default_c_compiler.html | 4 +- proc/get_default_cxx_compiler.html | 4 +- proc/get_default_flags.html | 6 +- proc/get_default_profiles.html | 4 +- proc/get_dos_path.html | 6 +- proc/get_env.html | 2 +- proc/get_exe_name_with_suffix.html | 4 +- proc/get_feature_flag.html | 6 +- proc/get_flags.html | 20 +- proc/get_fpm_env.html | 4 +- proc/get_global_settings.html | 4 +- proc/get_home.html | 6 +- proc/get_id.html | 4 +- proc/get_include_flag.html | 8 +- proc/get_list.html | 8 +- proc/get_local_prefix.html | 6 +- proc/get_macros.html | 8 +- proc/get_main_flags.html | 8 +- proc/get_module_flag.html | 8 +- proc/get_os_type.html | 4 +- proc/get_package_data.html | 4 +- proc/get_registry_settings.html | 6 +- proc/get_release_compile_flags.html | 4 +- proc/get_temp_filename.html | 2 +- proc/get_working_dir.html | 4 +- proc/getline.html | 10 +- proc/git_archive.html | 18 +- proc/git_is_same.html | 6 +- proc/git_matches_manifest.html | 6 +- proc/git_revision.html | 22 +- proc/git_target_branch.html | 4 +- proc/git_target_default.html | 4 +- proc/git_target_revision.html | 4 +- proc/git_target_tag.html | 4 +- proc/glob.html | 2 +- ...{handle_error~2.html => handle_error.html} | 4 +- proc/has_manifest.html | 4 +- proc/has_valid_custom_prefix.html | 4 +- proc/has_valid_standard_prefix.html | 6 +- proc/info_profile.html | 8 +- proc/{info~3.html => info~4.html} | 16 +- proc/{info~2.html => info~6.html} | 18 +- proc/is_absolute_path.html | 6 +- proc/is_dir.html | 4 +- proc/is_fortran_name.html | 4 +- proc/is_gnu.html | 4 +- proc/is_hidden_file.html | 4 +- proc/is_intel.html | 4 +- proc/is_meta_package.html | 2 +- proc/is_unknown.html | 4 +- proc/is_valid_module_name.html | 8 +- proc/is_valid_module_prefix.html | 4 +- proc/join.html | 6 +- proc/join_path.html | 4 +- proc/link.html | 8 +- proc/list_files.html | 8 +- ...from_toml~3.html => load_from_toml~4.html} | 12 +- ...from_toml~8.html => load_from_toml~9.html} | 10 +- proc/lower.html | 4 +- proc/make_archive.html | 10 +- proc/manifest_has_changed.html | 10 +- proc/match_os_type.html | 2 +- proc/mkdir.html | 6 +- proc/module_prefix_template.html | 4 +- proc/module_prefix_type.html | 2 +- proc/mpi_type_name.html | 4 +- proc/name_is_json.html | 2 +- proc/new_archiver.html | 12 +- proc/new_build_config.html | 10 +- proc/new_compiler.html | 8 +- proc/new_dependencies.html | 10 +- proc/new_dependency.html | 10 +- proc/new_dependency_node.html | 4 +- proc/new_dependency_tree.html | 6 +- proc/new_example.html | 8 +- proc/new_executable.html | 8 +- proc/new_fortran_config.html | 8 +- proc/new_install_config.html | 6 +- proc/new_installer.html | 8 +- proc/new_library.html | 8 +- proc/new_meta_config.html | 8 +- proc/new_meta_request.html | 8 +- proc/new_package.html | 10 +- proc/new_preprocess_config.html | 8 +- proc/new_preprocessors.html | 6 +- proc/new_profile.html | 8 +- proc/new_profiles.html | 16 +- proc/new_test.html | 8 +- proc/notabs.html | 2 +- proc/number_of_rows.html | 4 +- proc/os_delete_dir.html | 8 +- proc/os_is_unix.html | 4 +- proc/os_name.html | 4 +- proc/os_type_name.html | 2 +- proc/parent_dir.html | 6 +- proc/parse_c_source.html | 4 +- proc/parse_descriptor.html | 4 +- proc/parse_f_source.html | 11 +- proc/parse_use_statement.html | 10 +- proc/pkgcfg_get_build_flags.html | 6 +- proc/pkgcfg_get_libs.html | 6 +- proc/pkgcfg_get_version.html | 6 +- proc/pkgcfg_has_package.html | 4 +- proc/pkgcfg_list_all.html | 4 +- proc/profile_dump.html | 24 +- proc/profile_load.html | 28 +- proc/profile_same.html | 10 +- proc/read_lines.html | 6 +- proc/read_lines_expanded.html | 6 +- proc/read_package_file.html | 8 +- proc/regex_version_from_text.html | 6 +- proc/remove_characters_in_set.html | 4 +- proc/remove_newline_characters.html | 4 +- proc/replace.html | 4 +- proc/resolve_module_dependencies.html | 8 +- proc/run_wrapper.html | 4 +- proc/run~2.html | 8 +- proc/schedule_targets.html | 2 +- proc/separator.html | 4 +- proc/set_cpp_preprocessor_flags.html | 4 +- proc/set_env.html | 6 +- proc/set_list.html | 8 +- proc/show_model.html | 4 +- proc/sort_target.html | 2 +- proc/split.html | 2 +- proc/split_first_last.html | 4 +- proc/str_begins_with_str.html | 4 +- proc/string_array_contains.html | 2 +- proc/string_cat.html | 2 +- proc/syntax_error.html | 6 +- proc/targets_from_sources.html | 8 +- proc/to_fortran_name.html | 4 +- proc/traverse_compilers.html | 14 +- proc/traverse_oss.html | 14 +- proc/traverse_oss_for_size.html | 12 +- proc/unix_path.html | 4 +- proc/upper.html | 4 +- proc/validate_compiler_name.html | 2 +- proc/validate_os_name.html | 2 +- proc/validate_profile_table.html | 20 +- proc/warnwrite.html | 2 +- proc/which.html | 4 +- proc/windows_path.html | 4 +- proc/with_qp.html | 4 +- proc/with_xdp.html | 4 +- proc/write_response_file.html | 8 +- program/main.html | 28 +- search.html | 2 +- sourcefile/build.f90.html | 2 +- sourcefile/dependency.f90.html | 2 +- sourcefile/dependency.f90~2.html | 2 +- sourcefile/downloader.f90.html | 2 +- sourcefile/error.f90.html | 2 +- sourcefile/example.f90.html | 2 +- sourcefile/executable.f90.html | 2 +- sourcefile/export.f90.html | 2 +- sourcefile/fortran.f90.html | 2 +- sourcefile/fpm.f90.html | 2 +- sourcefile/fpm_backend.f90.html | 2 +- sourcefile/fpm_backend_console.f90.html | 2 +- sourcefile/fpm_backend_output.f90.html | 2 +- sourcefile/fpm_command_line.f90.html | 2 +- sourcefile/fpm_compiler.f90.html | 2 +- sourcefile/fpm_environment.f90.html | 2 +- sourcefile/fpm_filesystem.f90.html | 2 +- sourcefile/fpm_meta.f90.html | 2 +- sourcefile/fpm_model.f90.html | 4 +- sourcefile/fpm_os.f90.html | 2 +- sourcefile/fpm_pkg_config.f90.html | 2 +- sourcefile/fpm_release.f90.html | 2 +- sourcefile/fpm_settings.f90.html | 2 +- sourcefile/fpm_source_parsing.f90.html | 739 +++++++++--------- sourcefile/fpm_sources.f90.html | 2 +- sourcefile/fpm_strings.f90.html | 2 +- sourcefile/fpm_targets.f90.html | 2 +- sourcefile/git.f90.html | 2 +- sourcefile/install.f90.html | 2 +- sourcefile/install.f90~2.html | 2 +- sourcefile/installer.f90.html | 2 +- sourcefile/library.f90.html | 2 +- sourcefile/main.f90.html | 2 +- sourcefile/manifest.f90.html | 2 +- sourcefile/meta.f90.html | 2 +- sourcefile/new.f90.html | 2 +- sourcefile/package.f90.html | 2 +- sourcefile/preprocess.f90.html | 2 +- sourcefile/profiles.f90.html | 2 +- sourcefile/publish.f90.html | 2 +- sourcefile/test.f90.html | 2 +- sourcefile/toml.f90.html | 2 +- sourcefile/update.f90.html | 2 +- sourcefile/versioning.f90.html | 2 +- src/fpm_model.f90 | 2 +- src/fpm_source_parsing.f90 | 7 +- tipuesearch/tipuesearch_content.js | 2 +- type/archiver_t.html | 46 +- type/build_config_t.html | 48 +- type/build_progress_t.html | 10 +- type/build_target_ptr.html | 6 +- type/build_target_t.html | 14 +- type/compiler_t.html | 48 +- type/console_t.html | 2 +- type/dependency_config_t.html | 48 +- type/dependency_node_t.html | 48 +- type/dependency_tree_t.html | 44 +- type/downloader_t.html | 2 +- type/enum_descriptor.html | 6 +- type/error_t.html | 6 +- type/example_config_t.html | 32 +- type/executable_config_t.html | 36 +- type/file_scope_flag.html | 36 +- type/fortran_config_t.html | 44 +- type/fortran_features_t.html | 44 +- type/fpm_build_settings.html | 30 +- type/fpm_clean_settings.html | 6 +- type/fpm_cmd_settings.html | 6 +- type/fpm_export_settings.html | 30 +- type/fpm_global_settings.html | 2 +- type/fpm_install_settings.html | 42 +- type/fpm_model_t.html | 52 +- type/fpm_new_settings.html | 10 +- type/fpm_publish_settings.html | 30 +- type/fpm_run_settings.html | 42 +- type/fpm_test_settings.html | 42 +- type/fpm_update_settings.html | 10 +- type/git_target_t.html | 48 +- type/install_config_t.html | 36 +- type/installer_t.html | 18 +- type/library_config_t.html | 40 +- type/metapackage_config_t.html | 6 +- type/metapackage_request_t.html | 10 +- type/metapackage_t.html | 34 +- type/package_config_t.html | 72 +- type/package_t.html | 52 +- type/preprocess_config_t.html | 48 +- type/profile_config_t.html | 50 +- type/serializable_t.html | 24 +- type/srcfile_t.html | 32 +- type/string_t.html | 8 +- type/test_config_t.html | 32 +- type/version_t.html | 10 +- 390 files changed, 3180 insertions(+), 2849 deletions(-) rename proc/{dump_to_toml~3.html => dump_to_toml~4.html} (97%) rename proc/{dump_to_toml~8.html => dump_to_toml~9.html} (97%) create mode 100644 proc/fpm_unit_name.html rename proc/{handle_error~2.html => handle_error.html} (98%) rename proc/{info~3.html => info~4.html} (97%) rename proc/{info~2.html => info~6.html} (96%) rename proc/{load_from_toml~3.html => load_from_toml~4.html} (97%) rename proc/{load_from_toml~8.html => load_from_toml~9.html} (98%) diff --git a/index.html b/index.html index 7289c0a06d..ac642b560e 100644 --- a/index.html +++ b/index.html @@ -215,7 +215,7 @@

Derived Types

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/add_table.html b/interface/add_table.html index d1100afe9b..f6d39c9cf4 100644 --- a/interface/add_table.html +++ b/interface/add_table.html @@ -173,7 +173,7 @@

Arguments

- + type(toml_table), intent(inout) @@ -203,7 +203,7 @@

Arguments

- + type(toml_table), intent(out), @@ -218,7 +218,7 @@

Arguments

- + type(error_t), intent(out), @@ -270,7 +270,7 @@

Arguments

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/build_progress_t.html b/interface/build_progress_t.html index 43d33202a6..255b6eb3a0 100644 --- a/interface/build_progress_t.html +++ b/interface/build_progress_t.html @@ -229,7 +229,7 @@

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/debug.html b/interface/debug.html index edf86c19d6..4f6c3d4b93 100644 --- a/interface/debug.html +++ b/interface/debug.html @@ -174,7 +174,7 @@

Arguments

- + type(compiler_t), intent(in) @@ -219,7 +219,7 @@

Arguments

- + type(archiver_t), intent(in) @@ -261,7 +261,7 @@

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/fnv_1a.html b/interface/fnv_1a.html index 4a462c4dba..654d9ca738 100644 --- a/interface/fnv_1a.html +++ b/interface/fnv_1a.html @@ -173,7 +173,7 @@

Arguments

- + character(len=*), intent(in) @@ -232,7 +232,7 @@

Arguments

- + type(string_t), intent(in) @@ -289,7 +289,7 @@

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/get_value.html b/interface/get_value.html index 912629a7c4..f6613e6446 100644 --- a/interface/get_value.html +++ b/interface/get_value.html @@ -174,7 +174,7 @@

Arguments

- + type(toml_table), intent(inout) @@ -204,7 +204,7 @@

Arguments

- + logical, intent(inout) @@ -219,7 +219,7 @@

Arguments

- + type(error_t), intent(out), @@ -273,7 +273,7 @@

Arguments

- + type(toml_table), intent(inout) @@ -303,7 +303,7 @@

Arguments

- + integer, intent(inout) @@ -318,7 +318,7 @@

Arguments

- + type(error_t), intent(out), @@ -372,7 +372,7 @@

Arguments

- + type(toml_table), intent(inout) @@ -402,7 +402,7 @@

Arguments

- + integer(kind=int64), intent(inout) @@ -417,7 +417,7 @@

Arguments

- + type(error_t), intent(out), @@ -469,7 +469,7 @@

Arguments

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/len_trim.html b/interface/len_trim.html index 0debfb55bd..67b542cc1e 100644 --- a/interface/len_trim.html +++ b/interface/len_trim.html @@ -173,7 +173,7 @@

Arguments

- + type(string_t), intent(in) @@ -259,7 +259,7 @@

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/new_version.html b/interface/new_version.html index 02ed9855c6..a4a3a5c48b 100644 --- a/interface/new_version.html +++ b/interface/new_version.html @@ -173,7 +173,7 @@

Arguments

- + type(version_t), intent(out) @@ -188,7 +188,7 @@

Arguments

- + character(len=*), intent(in) @@ -203,7 +203,7 @@

Arguments

- + type(error_t), intent(out), @@ -242,7 +242,7 @@

Arguments

- + type(version_t), intent(out) @@ -257,7 +257,7 @@

Arguments

- + integer, intent(in) @@ -294,7 +294,7 @@

Arguments

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/operator(.in.).html b/interface/operator(.in.).html index 227e532a70..edec1bb3bf 100644 --- a/interface/operator(.in.).html +++ b/interface/operator(.in.).html @@ -230,7 +230,7 @@

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/operator(==).html b/interface/operator(==).html index 14f9ea9ab0..53c6354821 100644 --- a/interface/operator(==).html +++ b/interface/operator(==).html @@ -173,7 +173,7 @@

Arguments

- + type(string_t), intent(in) @@ -188,7 +188,7 @@

Arguments

- + type(string_t), intent(in) @@ -232,7 +232,7 @@

Arguments

- + type(string_t), intent(in), @@ -247,7 +247,7 @@

Arguments

- + type(string_t), intent(in), @@ -289,7 +289,7 @@

Documentation generated by FORD - on 2024-10-21 16:25

+ on 2024-10-21 16:43


diff --git a/interface/resize.html b/interface/resize.html index de41a2affc..51a33d3850 100644 --- a/interface/resize.html +++ b/interface/resize.html @@ -77,20 +77,20 @@

resize
  • 3 statements + title="

    0.0% of total for procedures.

    Including implementation: 27 statements, 0.4% of total for procedures.">3 statements
  • - Source File + Source File
  • @@ -154,10 +154,10 @@

    public interface resize

    Module Procedures

    -

    private subroutine resize_string(list, n) +

    private pure subroutine resize_dependency_config(var, n)

    -

    increase the size of a TYPE(STRING_T) array by N elements

    +

    Reallocate a list of dependencies

    Arguments

    @@ -172,22 +172,22 @@

    Arguments

    - + @@ -224,7 +224,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/interface/resize~2.html b/interface/resize~2.html index 11ff7153f2..9529907a0d 100644 --- a/interface/resize~2.html +++ b/interface/resize~2.html @@ -89,8 +89,8 @@

    resize @@ -148,13 +148,13 @@

    Module Procedures

    public interface resize

    - - +

    Overloaded reallocation interface

    +

    Module Procedures

    -

    private pure subroutine resize_dependency_config(var, n) +

    private pure subroutine resize_dependency_node(var, n)

    Reallocate a list of dependencies

    @@ -172,8 +172,8 @@

    Arguments

    @@ -224,7 +224,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/interface/resize~3.html b/interface/resize~3.html index 99c496a567..94081baa8b 100644 --- a/interface/resize~3.html +++ b/interface/resize~3.html @@ -77,20 +77,20 @@

    resize
  • 3 statements + title="

    0.0% of total for procedures.

    Including implementation: 29 statements, 0.5% of total for procedures.">3 statements
  • - Source File + Source File
  • @@ -134,7 +134,7 @@

    Module Procedures

    @@ -148,16 +148,16 @@

    Module Procedures

    public interface resize

    -

    Overloaded reallocation interface

    -
    + +

    Module Procedures

    -

    private pure subroutine resize_dependency_node(var, n) +

    private subroutine resize_string(list, n)

    -

    Reallocate a list of dependencies

    +

    increase the size of a TYPE(STRING_T) array by N elements

    Arguments

    - - type(string_t), + + type(dependency_config_t), intent(inout), allocatable ::list(:)var(:)

    Instance of the array to be resized

    - + integer, intent(in),
    - - type(dependency_config_t), + + type(dependency_node_t), intent(inout), @@ -187,7 +187,7 @@

    Arguments

    - + integer, intent(in),
    @@ -172,22 +172,22 @@

    Arguments

    - + @@ -224,7 +224,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/interface/resolve_metapackages.html b/interface/resolve_metapackages.html index 17939bb86b..e2288ebd84 100644 --- a/interface/resolve_metapackages.html +++ b/interface/resolve_metapackages.html @@ -172,7 +172,7 @@

    Arguments

    @@ -187,7 +187,7 @@

    Arguments

    @@ -202,7 +202,7 @@

    Arguments

    @@ -217,7 +217,7 @@

    Arguments

    @@ -254,7 +254,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/interface/set_string.html b/interface/set_string.html index 8204a4b23e..3ab963b227 100644 --- a/interface/set_string.html +++ b/interface/set_string.html @@ -174,7 +174,7 @@

    Arguments

    @@ -204,7 +204,7 @@

    Arguments

    @@ -219,7 +219,7 @@

    Arguments

    @@ -273,7 +273,7 @@

    Arguments

    @@ -303,7 +303,7 @@

    Arguments

    @@ -318,7 +318,7 @@

    Arguments

    @@ -370,7 +370,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/interface/set_value.html b/interface/set_value.html index 041ce2f6bb..e553970b1b 100644 --- a/interface/set_value.html +++ b/interface/set_value.html @@ -174,7 +174,7 @@

    Arguments

    @@ -204,7 +204,7 @@

    Arguments

    @@ -219,7 +219,7 @@

    Arguments

    @@ -273,7 +273,7 @@

    Arguments

    @@ -303,7 +303,7 @@

    Arguments

    @@ -318,7 +318,7 @@

    Arguments

    @@ -372,7 +372,7 @@

    Arguments

    @@ -402,7 +402,7 @@

    Arguments

    @@ -417,7 +417,7 @@

    Arguments

    @@ -469,7 +469,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/interface/str.html b/interface/str.html index 4471c49681..7636c40dfd 100644 --- a/interface/str.html +++ b/interface/str.html @@ -174,7 +174,7 @@

    Arguments

    @@ -218,7 +218,7 @@

    Arguments

    @@ -262,7 +262,7 @@

    Arguments

    @@ -304,7 +304,7 @@

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/interface/str_ends_with.html b/interface/str_ends_with.html index 779cff0d16..f40b05c94e 100644 --- a/interface/str_ends_with.html +++ b/interface/str_ends_with.html @@ -174,7 +174,7 @@

    Arguments

    @@ -233,7 +233,7 @@

    Arguments

    @@ -292,7 +292,7 @@

    Arguments

    @@ -349,7 +349,7 @@

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/interface/string_t.html b/interface/string_t.html index e07c29cf5a..ebe39823de 100644 --- a/interface/string_t.html +++ b/interface/string_t.html @@ -173,7 +173,7 @@

    Arguments

    @@ -215,7 +215,7 @@

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/lists/files.html b/lists/files.html index 0fbfd831a8..c0243eb55f 100644 --- a/lists/files.html +++ b/lists/files.html @@ -267,7 +267,7 @@

    Source Files

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/lists/modules.html b/lists/modules.html index 8dd2abb36e..859f4c6e9c 100644 --- a/lists/modules.html +++ b/lists/modules.html @@ -333,7 +333,7 @@

    Modules

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/lists/procedures.html b/lists/procedures.html index aef461c0b0..1c3b2efced 100644 --- a/lists/procedures.html +++ b/lists/procedures.html @@ -396,16 +396,16 @@

    Procedures

    - + - + - + @@ -533,6 +533,12 @@

    Procedures

    + + + + + + @@ -817,7 +823,7 @@

    Procedures

    contain wildcard characters.

    Read more… - + @@ -847,16 +853,16 @@

    Procedures

    3) If longer, package name must be followed by default separator plus at least one char

    Read more… - - + + - + - - + + - + @@ -963,13 +969,13 @@

    Procedures

    - + - + - + @@ -1334,21 +1340,21 @@

    Procedures

    - + - + - + - + - + @@ -1606,7 +1612,7 @@

    Procedures

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/lists/types.html b/lists/types.html index 39663a7589..6167fa7e81 100644 --- a/lists/types.html +++ b/lists/types.html @@ -369,7 +369,7 @@

    Derived Types

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm.html b/module/fpm.html index 38803700fb..1d2f2125d6 100644 --- a/module/fpm.html +++ b/module/fpm.html @@ -157,22 +157,22 @@

    Uses

    @@ -228,7 +228,7 @@

    Arguments

    @@ -243,7 +243,7 @@

    Arguments

    @@ -258,7 +258,7 @@

    Arguments

    @@ -298,7 +298,7 @@

    Arguments

    @@ -353,7 +353,7 @@

    Arguments

    @@ -394,7 +394,7 @@

    Arguments

    @@ -434,7 +434,7 @@

    Arguments

    @@ -449,7 +449,7 @@

    Arguments

    @@ -492,7 +492,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_backend.html b/module/fpm_backend.html index 6eb1bb59f6..151163678e 100644 --- a/module/fpm_backend.html +++ b/module/fpm_backend.html @@ -182,13 +182,13 @@

    Uses

    @@ -242,7 +242,7 @@

    Arguments

    @@ -257,7 +257,7 @@

    Arguments

    @@ -411,7 +411,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_backend_console.html b/module/fpm_backend_console.html index 6aa1835fa4..a1a8ae1f02 100644 --- a/module/fpm_backend_console.html +++ b/module/fpm_backend_console.html @@ -384,7 +384,7 @@

    Type-Bound Procedures

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_backend_output.html b/module/fpm_backend_output.html index 6e60fdef85..1a42ee42b4 100644 --- a/module/fpm_backend_output.html +++ b/module/fpm_backend_output.html @@ -172,10 +172,10 @@

    Uses

    @@ -292,7 +292,7 @@

    Components

    @@ -430,7 +430,7 @@

    Type-Bound Procedures

    + success => output_progress_success @@ -463,7 +463,7 @@

    Type-Bound Procedures

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_cmd_export.html b/module/fpm_cmd_export.html index 12c200b293..be76240413 100644 --- a/module/fpm_cmd_export.html +++ b/module/fpm_cmd_export.html @@ -154,11 +154,11 @@

    Uses

  • @@ -202,7 +202,7 @@

    Arguments

  • @@ -245,7 +245,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_cmd_install.html b/module/fpm_cmd_install.html index 3f9f2ac7c3..d344017f4c 100644 --- a/module/fpm_cmd_install.html +++ b/module/fpm_cmd_install.html @@ -154,16 +154,16 @@

    Uses

  • @@ -202,7 +202,7 @@

    Arguments

    @@ -245,7 +245,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_cmd_new.html b/module/fpm_cmd_new.html index d8a253c8d1..ec2061f204 100644 --- a/module/fpm_cmd_new.html +++ b/module/fpm_cmd_new.html @@ -194,9 +194,9 @@

    Uses

  • @@ -239,7 +239,7 @@

    Arguments

  • @@ -282,7 +282,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_cmd_publish.html b/module/fpm_cmd_publish.html index cdec40056c..d1bdf2ca10 100644 --- a/module/fpm_cmd_publish.html +++ b/module/fpm_cmd_publish.html @@ -155,17 +155,17 @@

    Uses

    @@ -206,7 +206,7 @@

    Arguments

    @@ -249,7 +249,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_cmd_update.html b/module/fpm_cmd_update.html index a0142ef99f..eecf477b3a 100644 --- a/module/fpm_cmd_update.html +++ b/module/fpm_cmd_update.html @@ -154,9 +154,9 @@

    Uses

  • @@ -197,7 +197,7 @@

    Arguments

  • @@ -240,7 +240,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_command_line.html b/module/fpm_command_line.html index eb0911af2f..715bc1ccb3 100644 --- a/module/fpm_command_line.html +++ b/module/fpm_command_line.html @@ -205,11 +205,11 @@

    Uses

  • @@ -253,7 +253,7 @@

    Components

  • @@ -287,7 +287,7 @@

    Components

    @@ -321,7 +321,7 @@

    Components

    @@ -338,7 +338,7 @@

    Components

    @@ -389,7 +389,7 @@

    Components

    @@ -423,7 +423,7 @@

    Components

    @@ -491,7 +491,7 @@

    Components

    @@ -608,7 +608,7 @@

    Components

    @@ -674,7 +674,7 @@

    Components

    @@ -740,7 +740,7 @@

    Components

    @@ -774,7 +774,7 @@

    Components

    @@ -808,7 +808,7 @@

    Components

    @@ -825,7 +825,7 @@

    Components

    @@ -927,7 +927,7 @@

    Components

    @@ -961,7 +961,7 @@

    Components

    @@ -1029,7 +1029,7 @@

    Components

    @@ -1095,7 +1095,7 @@

    Components

    @@ -1112,7 +1112,7 @@

    Components

    @@ -1146,7 +1146,7 @@

    Components

    @@ -1180,7 +1180,7 @@

    Components

    @@ -1197,7 +1197,7 @@

    Components

    @@ -1248,7 +1248,7 @@

    Components

    @@ -1299,7 +1299,7 @@

    Components

    @@ -1316,7 +1316,7 @@

    Components

    @@ -1350,7 +1350,7 @@

    Components

    @@ -1418,7 +1418,7 @@

    Components

    @@ -1501,7 +1501,7 @@

    Components

    @@ -1518,7 +1518,7 @@

    Components

    @@ -1686,7 +1686,7 @@

    Components

    @@ -1720,7 +1720,7 @@

    Components

    @@ -1754,7 +1754,7 @@

    Components

    @@ -1771,7 +1771,7 @@

    Components

    @@ -1822,7 +1822,7 @@

    Components

    @@ -1873,7 +1873,7 @@

    Components

    @@ -1992,7 +1992,7 @@

    Components

    @@ -2058,7 +2058,7 @@

    Components

    @@ -2075,7 +2075,7 @@

    Components

    @@ -2109,7 +2109,7 @@

    Components

    @@ -2143,7 +2143,7 @@

    Components

    @@ -2160,7 +2160,7 @@

    Components

    @@ -2211,7 +2211,7 @@

    Components

    @@ -2228,7 +2228,7 @@

    Components

    @@ -2262,7 +2262,7 @@

    Components

    @@ -2279,7 +2279,7 @@

    Components

    @@ -2381,7 +2381,7 @@

    Components

    @@ -2462,7 +2462,7 @@

    Components

    @@ -2479,7 +2479,7 @@

    Components

    @@ -2513,7 +2513,7 @@

    Components

    @@ -2547,7 +2547,7 @@

    Components

    @@ -2564,7 +2564,7 @@

    Components

    @@ -2615,7 +2615,7 @@

    Components

    @@ -2632,7 +2632,7 @@

    Components

    @@ -2666,7 +2666,7 @@

    Components

    @@ -2683,7 +2683,7 @@

    Components

    @@ -2785,7 +2785,7 @@

    Components

    @@ -2917,7 +2917,7 @@

    Components

    @@ -2934,7 +2934,7 @@

    Components

    @@ -3110,7 +3110,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_compiler.html b/module/fpm_compiler.html index d66f9b8279..1ad83cc398 100644 --- a/module/fpm_compiler.html +++ b/module/fpm_compiler.html @@ -280,14 +280,14 @@

    Subroutines

    compile_fortrancompiler_dumpcompiler_load - dump_to_toml + dump_to_tomlget_debug_compile_flagsget_default_c_compilerget_default_cxx_compilerget_main_flagsget_release_compile_flagslink - load_from_toml + load_from_tomlmake_archivenew_archivernew_compiler @@ -319,11 +319,11 @@

    Uses

    @@ -1785,7 +1785,7 @@

    Arguments

    @@ -1859,7 +1859,7 @@

    Components

    @@ -1893,7 +1893,7 @@

    Components

    @@ -1919,22 +1919,22 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + load => load_from_toml, load_from_file, load_from_unit + load_from_toml @@ -1944,12 +1944,12 @@

    Type-Bound Procedures

    + operator(==) => serializable_is_same + serializable_is_same => ar_is_same @@ -2021,7 +2021,7 @@

    Components

    @@ -2072,7 +2072,7 @@

    Components

    @@ -2118,12 +2118,12 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml => compiler_dump @@ -2173,32 +2173,32 @@

    Type-Bound Procedures

    + link + load => load_from_toml, load_from_file, load_from_unit + load_from_toml => compiler_load + name => compiler_name + operator(==) => serializable_is_same + serializable_is_same => compiler_is_same @@ -2247,7 +2247,7 @@

    Arguments

    @@ -2262,7 +2262,7 @@

    Arguments

    @@ -2307,7 +2307,7 @@

    Arguments

    @@ -2372,7 +2372,7 @@

    Arguments

    @@ -2387,7 +2387,7 @@

    Arguments

    @@ -2433,7 +2433,7 @@

    Arguments

    @@ -2448,7 +2448,7 @@

    Arguments

    @@ -2493,7 +2493,7 @@

    Arguments

    @@ -2538,7 +2538,7 @@

    Arguments

    @@ -2583,7 +2583,7 @@

    Arguments

    @@ -2628,7 +2628,7 @@

    Arguments

    @@ -2643,7 +2643,7 @@

    Arguments

    @@ -2658,7 +2658,7 @@

    Arguments

    @@ -2703,7 +2703,7 @@

    Arguments

    @@ -2748,7 +2748,7 @@

    Arguments

    @@ -2808,7 +2808,7 @@

    Arguments

    @@ -2868,7 +2868,7 @@

    Arguments

    @@ -2913,7 +2913,7 @@

    Arguments

    @@ -2928,7 +2928,7 @@

    Arguments

    @@ -3007,7 +3007,7 @@

    Arguments

    @@ -3052,7 +3052,7 @@

    Arguments

    @@ -3067,7 +3067,7 @@

    Arguments

    @@ -3112,7 +3112,7 @@

    Arguments

    @@ -3157,7 +3157,7 @@

    Arguments

    @@ -3202,7 +3202,7 @@

    Arguments

    @@ -3247,7 +3247,7 @@

    Arguments

    @@ -3292,7 +3292,7 @@

    Arguments

    @@ -3342,7 +3342,7 @@

    Arguments

    @@ -3357,7 +3357,7 @@

    Arguments

    @@ -3372,7 +3372,7 @@

    Arguments

    @@ -3417,7 +3417,7 @@

    Arguments

    @@ -3457,7 +3457,7 @@

    Arguments

    @@ -3472,7 +3472,7 @@

    Arguments

    @@ -3487,7 +3487,7 @@

    Arguments

    @@ -3532,7 +3532,7 @@

    Arguments

    @@ -3572,7 +3572,7 @@

    Arguments

    @@ -3587,7 +3587,7 @@

    Arguments

    @@ -3602,7 +3602,7 @@

    Arguments

    @@ -3647,7 +3647,7 @@

    Arguments

    @@ -3687,7 +3687,7 @@

    Arguments

    @@ -3702,7 +3702,7 @@

    Arguments

    @@ -3717,7 +3717,7 @@

    Arguments

    @@ -3757,7 +3757,7 @@

    Arguments

    @@ -3772,7 +3772,7 @@

    Arguments

    @@ -3787,7 +3787,7 @@

    Arguments

    @@ -3808,11 +3808,11 @@

    Arguments

    -

    public subroutine dump_to_toml(self, table, error) +

    public subroutine dump_to_toml(self, table, error)

    -

    Dump dependency to toml table

    Read more… +

    Dump dependency to toml table

    Read more…

    Arguments

    - - type(dependency_node_t), + + type(string_t), intent(inout), allocatable ::var(:)list(:)

    Instance of the array to be resized

    - + integer, intent(in),
    - + type(fpm_model_t), intent(inout)
    - + type(package_config_t), intent(inout)
    - + class(fpm_build_settings), intent(inout)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + character(len=*), intent(in),
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + type(string_t), intent(in)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + logical, intent(in)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + integer, intent(in)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + integer(kind=int64), intent(in)
    - + type(error_t), intent(out),
    - + integer, intent(in)
    - + integer(kind=int64), intent(in)
    - + logical, intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)

    Extract dirname from path

    dump_to_tomldump_to_toml fpm_git Subroutine

    Dump dependency to toml table

    dump_to_tomldump_to_toml fpm_compiler Subroutine

    Dump dependency to toml table

    Read more…

    Dump dependency to toml table

    Read more…
    enumerate_libraries fpm_targets Function

    Target type name

    FPM_UNIT_NAMEfpm_modelFunction

    Return the character name of a unit flag

    fpm_version
    handle_errorhandle_error main Subroutine
    infofpm_manifest_profileinfofpm_git Subroutine

    Write information on instance

    Show information on git target

    infofpm_gitinfofpm_manifest_profile Subroutine

    Show information on git target

    Write information on instance

    info_profile

    Get file & directory names in directory dir using iso_c_binding.

    Read more…
    load_from_tomlload_from_toml fpm_git Subroutine

    Read dependency from toml table (no checks made at this stage)

    Read more…

    Read dependency from toml table (no checks made at this stage)

    Read more…
    load_from_tomlload_from_toml fpm_compiler Subroutine

    Read dependency from toml table (no checks made at this stage)

    resizefpm_stringsfpm_manifest_dependency Interface
    resizefpm_manifest_dependencyfpm_dependency Interface

    Overloaded reallocation interface

    resizefpm_dependencyfpm_strings Interface

    Overloaded reallocation interface

    resolve_metapackages
    - + type(fpm_model_t), intent(out)
    - + class(fpm_build_settings), intent(inout)
    - + type(package_config_t), intent(inout)
    - + type(error_t), intent(out),
    - + type(fpm_model_t), intent(in)
    - + type(fpm_build_settings), intent(inout)
    - + class(fpm_clean_settings), intent(in)
    - + class(fpm_run_settings), intent(inout)
    - + logical, intent(in)
    - + type(fpm_model_t), intent(in)
    - + logical, intent(in)
    - + type(console_t), public
    procedure, public :: - success => output_progress_success ../../

    Output finished status for whole package

    - + type(fpm_export_settings), intent(inout)
    - + type(fpm_install_settings), intent(inout)
    - + type(fpm_new_settings), intent(in)
    - + type(fpm_publish_settings), intent(inout)
    - + type(fpm_update_settings), intent(in)
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + logical, public
    - + logical, public
    - + logical, public
    - + logical, public
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + logical, public
    - + logical, public
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + logical, public
    - + character(len=:), public,
    - + logical, public
    - + character(len=:), public,
    - + logical, public
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + logical, public
    - + logical, public
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + logical, public
    - + character(len=:), public,
    - + logical, public
    - + character(len=ibug), public,
    - + logical, public
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    - + logical, public
    - + character(len=:), public,
    - + logical, public
    - + character(len=ibug), public,
    - + logical, public
    - + character(len=ibug), public,
    - + logical, public
    - + type(compiler_t), intent(in)
    - + type(archiver_t), intent(in)
    - + logical, public
    - + logical, public
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => ar_is_same ../../

    Serialization interface

    - + logical, public
    - + logical, public
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => compiler_dump
    procedure, public :: - link ../../

    Link executable

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => compiler_load
    procedure, public :: - name => compiler_name ../../

    Return compiler name

    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => compiler_is_same ../../

    Serialization interface

    - + class(archiver_t), intent(in)
    - + class(serializable_t), intent(in)
    - + character(len=*), intent(in)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + class(compiler_t), intent(in)
    - + class(serializable_t), intent(in)
    - + class(compiler_t), intent(in)
    - + type(archiver_t), intent(in)
    - + type(compiler_t), intent(in)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + type(string_t), intent(in)
    - + character(len=*), intent(in)
    - + class(compiler_t), intent(in)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=:), intent(in),
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + class(compiler_t), intent(in)
    - + class(compiler_t), intent(in)
    - + class(compiler_t), intent(in)
    - + class(compiler_t), intent(in)
    - + class(compiler_t), intent(in)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + class(compiler_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + class(compiler_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    @@ -3827,7 +3827,7 @@

    Arguments

    @@ -3842,7 +3842,7 @@

    Arguments

    @@ -3857,7 +3857,7 @@

    Arguments

    @@ -3912,7 +3912,7 @@

    Arguments

    @@ -3967,7 +3967,7 @@

    Arguments

    @@ -4022,7 +4022,7 @@

    Arguments

    @@ -4062,7 +4062,7 @@

    Arguments

    @@ -4077,7 +4077,7 @@

    Arguments

    @@ -4092,7 +4092,7 @@

    Arguments

    @@ -4147,7 +4147,7 @@

    Arguments

    @@ -4187,7 +4187,7 @@

    Arguments

    @@ -4202,7 +4202,7 @@

    Arguments

    @@ -4247,7 +4247,7 @@

    Arguments

    @@ -4268,7 +4268,7 @@

    Arguments

    -

    public subroutine load_from_toml(self, table, error) +

    public subroutine load_from_toml(self, table, error)

    @@ -4287,7 +4287,7 @@

    Arguments

    @@ -4302,7 +4302,7 @@

    Arguments

    @@ -4317,7 +4317,7 @@

    Arguments

    @@ -4357,7 +4357,7 @@

    Arguments

    @@ -4372,7 +4372,7 @@

    Arguments

    @@ -4417,7 +4417,7 @@

    Arguments

    @@ -4457,7 +4457,7 @@

    Arguments

    @@ -4487,7 +4487,7 @@

    Arguments

    @@ -4502,7 +4502,7 @@

    Arguments

    @@ -4542,7 +4542,7 @@

    Arguments

    @@ -4602,7 +4602,7 @@

    Arguments

    @@ -4617,7 +4617,7 @@

    Arguments

    @@ -4672,7 +4672,7 @@

    Arguments

    @@ -4715,7 +4715,7 @@

    Arguments

    @@ -4773,7 +4773,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_dependency.html b/module/fpm_dependency.html index 8ffc7d50e4..9ac8a440af 100644 --- a/module/fpm_dependency.html +++ b/module/fpm_dependency.html @@ -123,7 +123,7 @@

    Interfaces

    @@ -226,19 +226,19 @@

    Uses

    @@ -299,7 +299,7 @@

    Arguments

    @@ -402,7 +402,7 @@

    Components

    @@ -438,7 +438,7 @@

    Components

    @@ -455,7 +455,7 @@

    Components

    @@ -567,12 +567,12 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml => node_dump_to_toml @@ -582,22 +582,22 @@

    Type-Bound Procedures

    + info + load => load_from_toml, load_from_file, load_from_unit + load_from_toml => node_load_from_toml + operator(==) => serializable_is_same @@ -607,7 +607,7 @@

    Type-Bound Procedures

    + serializable_is_same => dependency_node_is_same @@ -713,7 +713,7 @@

    Components

    @@ -730,7 +730,7 @@

    Components

    @@ -761,7 +761,7 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit @@ -771,7 +771,7 @@

    Type-Bound Procedures

    + dump_to_toml => tree_dump_to_toml @@ -791,7 +791,7 @@

    Type-Bound Procedures

    + load => load_from_toml, load_from_file, load_from_unit @@ -801,22 +801,22 @@

    Type-Bound Procedures

    + load_from_toml => tree_load_from_toml + operator(==) => serializable_is_same + resolve => resolve_dependencies, resolve_dependency + serializable_is_same => dependency_tree_is_same @@ -875,7 +875,7 @@

    Arguments

    @@ -920,7 +920,7 @@

    Arguments

    @@ -960,7 +960,7 @@

    Arguments

    @@ -1000,7 +1000,7 @@

    Arguments

    @@ -1100,7 +1100,7 @@

    Arguments

    @@ -1115,7 +1115,7 @@

    Arguments

    @@ -1173,7 +1173,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_downloader.html b/module/fpm_downloader.html index 9af3d345ff..d3ed2d7a09 100644 --- a/module/fpm_downloader.html +++ b/module/fpm_downloader.html @@ -242,7 +242,7 @@

    Type-Bound Procedures

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_environment.html b/module/fpm_environment.html index 16df2d3721..cdd9d2a023 100644 --- a/module/fpm_environment.html +++ b/module/fpm_environment.html @@ -182,9 +182,9 @@

    Uses

    @@ -375,7 +375,7 @@

    Arguments

    @@ -421,7 +421,7 @@

    Arguments

    @@ -567,7 +567,7 @@

    Arguments

    @@ -630,7 +630,7 @@

    Arguments

    @@ -645,7 +645,7 @@

    Arguments

    @@ -709,7 +709,7 @@

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_error.html b/module/fpm_error.html index 35ff5a8962..c0117ae26d 100644 --- a/module/fpm_error.html +++ b/module/fpm_error.html @@ -179,8 +179,8 @@

    Uses

    @@ -222,7 +222,7 @@

    Components

    @@ -271,7 +271,7 @@

    Arguments

    @@ -301,7 +301,7 @@

    Arguments

    @@ -351,7 +351,7 @@

    Arguments

    @@ -366,7 +366,7 @@

    Arguments

    @@ -406,7 +406,7 @@

    Arguments

    @@ -461,7 +461,7 @@

    Arguments

    @@ -491,7 +491,7 @@

    Arguments

    @@ -591,7 +591,7 @@

    Arguments

    @@ -631,7 +631,7 @@

    Arguments

    @@ -646,7 +646,7 @@

    Arguments

    @@ -689,7 +689,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_filesystem.html b/module/fpm_filesystem.html index fb944de4fe..33306eb48b 100644 --- a/module/fpm_filesystem.html +++ b/module/fpm_filesystem.html @@ -193,10 +193,10 @@

    Uses

    @@ -297,7 +297,7 @@

    Arguments

    @@ -342,7 +342,7 @@

    Arguments

    @@ -387,7 +387,7 @@

    Arguments

    @@ -433,7 +433,7 @@

    Arguments

    @@ -448,7 +448,7 @@

    Arguments

    @@ -493,7 +493,7 @@

    Arguments

    @@ -560,7 +560,7 @@

    Arguments

    @@ -575,7 +575,7 @@

    Arguments

    @@ -620,7 +620,7 @@

    Arguments

    @@ -815,7 +815,7 @@

    Arguments

    @@ -860,7 +860,7 @@

    Arguments

    @@ -905,7 +905,7 @@

    Arguments

    @@ -950,7 +950,7 @@

    Arguments

    @@ -995,7 +995,7 @@

    Arguments

    @@ -1044,7 +1044,7 @@

    Arguments

    @@ -1089,7 +1089,7 @@

    Arguments

    @@ -1139,7 +1139,7 @@

    Arguments

    @@ -1179,7 +1179,7 @@

    Arguments

    @@ -1194,7 +1194,7 @@

    Arguments

    @@ -1209,7 +1209,7 @@

    Arguments

    @@ -1224,7 +1224,7 @@

    Arguments

    @@ -1264,7 +1264,7 @@

    Arguments

    @@ -1319,7 +1319,7 @@

    Arguments

    @@ -1334,7 +1334,7 @@

    Arguments

    @@ -1389,7 +1389,7 @@

    Arguments

    @@ -1444,7 +1444,7 @@

    Arguments

    @@ -1459,7 +1459,7 @@

    Arguments

    @@ -1503,7 +1503,7 @@

    Arguments

    @@ -1518,7 +1518,7 @@

    Arguments

    @@ -1533,7 +1533,7 @@

    Arguments

    @@ -1548,7 +1548,7 @@

    Arguments

    @@ -1588,7 +1588,7 @@

    Arguments

    @@ -1603,7 +1603,7 @@

    Arguments

    @@ -1618,7 +1618,7 @@

    Arguments

    @@ -1658,7 +1658,7 @@

    Arguments

    @@ -1673,7 +1673,7 @@

    Arguments

    @@ -1713,7 +1713,7 @@

    Arguments

    @@ -1728,7 +1728,7 @@

    Arguments

    @@ -1743,7 +1743,7 @@

    Arguments

    @@ -1787,7 +1787,7 @@

    Arguments

    @@ -1802,7 +1802,7 @@

    Arguments

    @@ -1832,7 +1832,7 @@

    Arguments

    @@ -1945,7 +1945,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_git.html b/module/fpm_git.html index 489aa072f3..eaed7c3311 100644 --- a/module/fpm_git.html +++ b/module/fpm_git.html @@ -118,7 +118,7 @@

    Variables

    @@ -171,11 +171,11 @@

    Subroutines

    @@ -201,8 +201,8 @@

    Uses

    @@ -347,7 +347,7 @@

    Components

    @@ -447,7 +447,7 @@

    Components

    @@ -495,37 +495,37 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + info + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same => git_is_same @@ -609,7 +609,7 @@

    Arguments

    @@ -624,7 +624,7 @@

    Arguments

    @@ -669,7 +669,7 @@

    Arguments

    @@ -714,7 +714,7 @@

    Arguments

    @@ -984,7 +984,7 @@

    Arguments

    @@ -1034,7 +1034,7 @@

    Arguments

    @@ -1064,7 +1064,7 @@

    Arguments

    @@ -1085,7 +1085,7 @@

    Arguments

    -

    public subroutine dump_to_toml(self, table, error) +

    public subroutine dump_to_toml(self, table, error)

    @@ -1104,7 +1104,7 @@

    Arguments

    @@ -1119,7 +1119,7 @@

    Arguments

    @@ -1134,7 +1134,7 @@

    Arguments

    @@ -1174,7 +1174,7 @@

    Arguments

    @@ -1189,7 +1189,7 @@

    Arguments

    @@ -1234,7 +1234,7 @@

    Arguments

    @@ -1249,7 +1249,7 @@

    Arguments

    @@ -1304,7 +1304,7 @@

    Arguments

    @@ -1319,7 +1319,7 @@

    Arguments

    @@ -1340,7 +1340,7 @@

    Arguments

    -

    public subroutine info(self, unit, verbosity) +

    public subroutine info(self, unit, verbosity)

    @@ -1359,7 +1359,7 @@

    Arguments

    @@ -1374,7 +1374,7 @@

    Arguments

    @@ -1410,11 +1410,11 @@

    Arguments

    -

    public subroutine load_from_toml(self, table, error) +

    public subroutine load_from_toml(self, table, error)

    -

    Read dependency from toml table (no checks made at this stage)

    Read more… +

    Read dependency from toml table (no checks made at this stage)

    Read more…

    Arguments

    - + class(archiver_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + character(len=:), intent(out),
    - + character(len=:), intent(out),
    - + character(len=:), intent(out),
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=:), intent(out),
    - + character(len=:), intent(out),
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + class(archiver_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + class(archiver_t), intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + type(archiver_t), intent(out)
    - + logical, intent(in)
    - + logical, intent(in)
    - + type(compiler_t), intent(out)
    - + logical, intent(in)
    - + logical, intent(in)
    - + character(len=:), intent(inout),
    - + character(len=*), intent(in)
    - + type(dependency_node_t), intent(inout),
    - + integer, intent(in),
    - + character(len=:), public,
    - + character(len=:), public,
    - + type(preprocess_config_t), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => node_dump_to_toml
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => node_load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => dependency_node_is_same ../../

    Serialization interface

    - + integer, public
    - + integer, public
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => tree_dump_to_toml
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => tree_load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    generic, public :: - resolve => resolve_dependencies, resolve_dependency ../../

    Resolve dependencies

    procedure, public :: - serializable_is_same => dependency_tree_is_same ../../

    Serialization interface

    - + class(dependency_node_t), intent(in)
    - + type(error_t), intent(out),
    - + class(dependency_node_t), intent(inout)
    - + type(dependency_node_t), intent(out)
    - + type(dependency_tree_t), intent(out)
    - + integer, intent(in),
    - + integer, intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(in),
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=:), public,
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + integer, intent(in),
    - + character(len=*), intent(in)
    - + logical, intent(in),
    - + character(len=*), intent(in)
    - + integer, intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=:), intent(out),
    - + type(error_t), intent(out),
    - + logical, intent(in),
    - + integer, intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + character(len=*), intent(in)
    - + character(len=:), intent(out),
    - + type(error_t), intent(out),
    - + integer, intent(in)
    - + character(len=:), intent(out),
    - + integer, intent(out)
    - + character(len=:),
    - + character(len=*), intent(in)
    - + type(string_t), intent(out),
    - + logical, intent(in),
    - + character(len=*), intent(in)
    - + logical, intent(in),
    - + logical, intent(in)
    - + character(len=*), intent(in)
    - + logical, intent(in),
    - + character(len=*), intent(in)
    - + logical, intent(in),
    - + logical, intent(in),
    - + character(len=*), public,
    - + integer, public
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    procedure, public :: - info ../../

    Show information on instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => git_is_same ../../

    Serialization interface

    - + class(git_target_t), intent(in)
    - + class(serializable_t), intent(in)
    - + type(git_target_t), intent(in)
    - + integer, intent(in)
    - + character(len=*), intent(in)
    - + class(git_target_t), intent(in)
    - + type(error_t), intent(out),
    - + class(git_target_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + logical, intent(in)
    - + type(error_t), intent(out),
    - + character(len=:), intent(out),
    - + type(error_t), intent(out),
    - + class(git_target_t), intent(in)
    - + integer, intent(in)
    @@ -1429,7 +1429,7 @@

    Arguments

    @@ -1444,7 +1444,7 @@

    Arguments

    @@ -1459,7 +1459,7 @@

    Arguments

    @@ -1502,7 +1502,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_installer.html b/module/fpm_installer.html index 9a6a471d6a..c7b2034349 100644 --- a/module/fpm_installer.html +++ b/module/fpm_installer.html @@ -167,10 +167,10 @@

    Uses

    @@ -229,7 +229,7 @@

    Components

    @@ -297,7 +297,7 @@

    Components

    @@ -331,7 +331,7 @@

    Components

    @@ -348,7 +348,7 @@

    Components

    @@ -433,7 +433,7 @@

    Arguments

    @@ -508,7 +508,7 @@

    Arguments

    @@ -523,7 +523,7 @@

    Arguments

    @@ -581,7 +581,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest.html b/module/fpm_manifest.html index 69fa4c76ca..d298c199a7 100644 --- a/module/fpm_manifest.html +++ b/module/fpm_manifest.html @@ -162,18 +162,18 @@

    Uses

    @@ -212,7 +212,7 @@

    Arguments

    @@ -227,7 +227,7 @@

    Arguments

    @@ -267,7 +267,7 @@

    Arguments

    @@ -282,7 +282,7 @@

    Arguments

    @@ -322,7 +322,7 @@

    Arguments

    @@ -362,7 +362,7 @@

    Arguments

    @@ -377,7 +377,7 @@

    Arguments

    @@ -447,7 +447,7 @@

    Arguments

    @@ -505,7 +505,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_build.html b/module/fpm_manifest_build.html index 6422240c27..92d2ab022c 100644 --- a/module/fpm_manifest_build.html +++ b/module/fpm_manifest_build.html @@ -171,9 +171,9 @@

    Uses

    @@ -266,7 +266,7 @@

    Components

    @@ -283,7 +283,7 @@

    Components

    @@ -317,7 +317,7 @@

    Components

    @@ -343,37 +343,37 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + info + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same => build_conf_is_same @@ -412,7 +412,7 @@

    Arguments

    @@ -427,7 +427,7 @@

    Arguments

    @@ -442,7 +442,7 @@

    Arguments

    @@ -457,7 +457,7 @@

    Arguments

    @@ -500,7 +500,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_dependency.html b/module/fpm_manifest_dependency.html index 2f58f5e3ff..1f9d0c869e 100644 --- a/module/fpm_manifest_dependency.html +++ b/module/fpm_manifest_dependency.html @@ -123,7 +123,7 @@

    Interfaces

    @@ -207,14 +207,14 @@

    Uses

    @@ -272,7 +272,7 @@

    Arguments

    @@ -341,7 +341,7 @@

    Components

    @@ -377,7 +377,7 @@

    Components

    @@ -394,7 +394,7 @@

    Components

    @@ -438,37 +438,37 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + info + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same => dependency_is_same @@ -506,7 +506,7 @@

    Arguments

    @@ -521,7 +521,7 @@

    Arguments

    @@ -536,7 +536,7 @@

    Arguments

    @@ -551,7 +551,7 @@

    Arguments

    @@ -601,7 +601,7 @@

    Arguments

    @@ -656,7 +656,7 @@

    Arguments

    @@ -671,7 +671,7 @@

    Arguments

    @@ -686,7 +686,7 @@

    Arguments

    @@ -701,7 +701,7 @@

    Arguments

    @@ -741,7 +741,7 @@

    Arguments

    @@ -756,7 +756,7 @@

    Arguments

    @@ -771,7 +771,7 @@

    Arguments

    @@ -786,7 +786,7 @@

    Arguments

    @@ -829,7 +829,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_example.html b/module/fpm_manifest_example.html index a21bd9235e..e5fcf62228 100644 --- a/module/fpm_manifest_example.html +++ b/module/fpm_manifest_example.html @@ -175,10 +175,10 @@

    Uses

    @@ -237,7 +237,7 @@

    Components

    @@ -271,7 +271,7 @@

    Components

    @@ -288,7 +288,7 @@

    Components

    @@ -314,7 +314,7 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit @@ -329,7 +329,7 @@

    Type-Bound Procedures

    + load => load_from_toml, load_from_file, load_from_unit @@ -339,7 +339,7 @@

    Type-Bound Procedures

    + operator(==) => serializable_is_same @@ -383,7 +383,7 @@

    Arguments

    @@ -398,7 +398,7 @@

    Arguments

    @@ -413,7 +413,7 @@

    Arguments

    @@ -456,7 +456,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_executable.html b/module/fpm_manifest_executable.html index ef09f2c0c0..9f9be0fdba 100644 --- a/module/fpm_manifest_executable.html +++ b/module/fpm_manifest_executable.html @@ -172,10 +172,10 @@

    Uses

    @@ -234,7 +234,7 @@

    Components

    @@ -268,7 +268,7 @@

    Components

    @@ -285,7 +285,7 @@

    Components

    @@ -311,7 +311,7 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit @@ -321,12 +321,12 @@

    Type-Bound Procedures

    + info + load => load_from_toml, load_from_file, load_from_unit @@ -336,7 +336,7 @@

    Type-Bound Procedures

    + operator(==) => serializable_is_same @@ -380,7 +380,7 @@

    Arguments

    @@ -395,7 +395,7 @@

    Arguments

    @@ -410,7 +410,7 @@

    Arguments

    @@ -453,7 +453,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_fortran.html b/module/fpm_manifest_fortran.html index 4c68d88c2c..4e4572dd23 100644 --- a/module/fpm_manifest_fortran.html +++ b/module/fpm_manifest_fortran.html @@ -164,8 +164,8 @@

    Uses

    @@ -207,7 +207,7 @@

    Components

    @@ -224,7 +224,7 @@

    Components

    @@ -241,7 +241,7 @@

    Components

    @@ -267,32 +267,32 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same => fortran_is_same @@ -331,7 +331,7 @@

    Arguments

    @@ -346,7 +346,7 @@

    Arguments

    @@ -361,7 +361,7 @@

    Arguments

    @@ -404,7 +404,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_install.html b/module/fpm_manifest_install.html index 302b93368c..91c2e9c8cf 100644 --- a/module/fpm_manifest_install.html +++ b/module/fpm_manifest_install.html @@ -167,8 +167,8 @@

    Uses

    @@ -236,37 +236,37 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + info + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same => install_conf_same @@ -320,7 +320,7 @@

    Arguments

    @@ -335,7 +335,7 @@

    Arguments

    @@ -378,7 +378,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_library.html b/module/fpm_manifest_library.html index 416b2c41f2..0f44c74890 100644 --- a/module/fpm_manifest_library.html +++ b/module/fpm_manifest_library.html @@ -170,9 +170,9 @@

    Uses

    @@ -248,7 +248,7 @@

    Components

    @@ -274,37 +274,37 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + info + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same => library_is_same @@ -343,7 +343,7 @@

    Arguments

    @@ -358,7 +358,7 @@

    Arguments

    @@ -373,7 +373,7 @@

    Arguments

    @@ -416,7 +416,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_metapackages.html b/module/fpm_manifest_metapackages.html index a396dac7a2..4b35181646 100644 --- a/module/fpm_manifest_metapackages.html +++ b/module/fpm_manifest_metapackages.html @@ -183,9 +183,9 @@

    Uses

    @@ -261,7 +261,7 @@

    Components

    @@ -344,7 +344,7 @@

    Components

    @@ -378,7 +378,7 @@

    Components

    @@ -477,7 +477,7 @@

    Arguments

    @@ -492,7 +492,7 @@

    Arguments

    @@ -522,7 +522,7 @@

    Arguments

    @@ -562,7 +562,7 @@

    Arguments

    @@ -592,7 +592,7 @@

    Arguments

    @@ -622,7 +622,7 @@

    Arguments

    @@ -665,7 +665,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_package.html b/module/fpm_manifest_package.html index 787b15c6ba..92f4e5b679 100644 --- a/module/fpm_manifest_package.html +++ b/module/fpm_manifest_package.html @@ -193,21 +193,21 @@

    Uses

    @@ -300,7 +300,7 @@

    Components

    @@ -334,7 +334,7 @@

    Components

    @@ -368,7 +368,7 @@

    Components

    @@ -453,7 +453,7 @@

    Components

    @@ -470,7 +470,7 @@

    Components

    @@ -487,7 +487,7 @@

    Components

    @@ -504,7 +504,7 @@

    Components

    @@ -521,7 +521,7 @@

    Components

    @@ -538,7 +538,7 @@

    Components

    @@ -564,37 +564,37 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + info + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same => manifest_is_same @@ -633,7 +633,7 @@

    Arguments

    @@ -648,7 +648,7 @@

    Arguments

    @@ -663,7 +663,7 @@

    Arguments

    @@ -678,7 +678,7 @@

    Arguments

    @@ -721,7 +721,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_preprocess.html b/module/fpm_manifest_preprocess.html index a059f419fe..3bc001b58f 100644 --- a/module/fpm_manifest_preprocess.html +++ b/module/fpm_manifest_preprocess.html @@ -172,10 +172,10 @@

    Uses

    @@ -251,7 +251,7 @@

    Components

    @@ -268,7 +268,7 @@

    Components

    @@ -299,22 +299,22 @@

    Type-Bound Procedures

    + destroy + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + info @@ -329,22 +329,22 @@

    Type-Bound Procedures

    + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same => preprocess_is_same @@ -383,7 +383,7 @@

    Arguments

    @@ -398,7 +398,7 @@

    Arguments

    @@ -413,7 +413,7 @@

    Arguments

    @@ -468,7 +468,7 @@

    Arguments

    @@ -483,7 +483,7 @@

    Arguments

    @@ -526,7 +526,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_profile.html b/module/fpm_manifest_profile.html index aadfd004e5..e5daa66ad9 100644 --- a/module/fpm_manifest_profile.html +++ b/module/fpm_manifest_profile.html @@ -172,7 +172,7 @@

    Subroutines

    file_scope_loadfind_profileget_flags - info + infomatch_os_typenew_profilesprofile_dump @@ -247,10 +247,10 @@

    Uses

    @@ -404,32 +404,32 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml => file_scope_dump + load => load_from_toml, load_from_file, load_from_unit + load_from_toml => file_scope_load + operator(==) => serializable_is_same + serializable_is_same => file_scope_same @@ -484,7 +484,7 @@

    Components

    @@ -535,7 +535,7 @@

    Components

    @@ -603,7 +603,7 @@

    Components

    @@ -629,37 +629,37 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml => profile_dump + info + load => load_from_toml, load_from_file, load_from_unit + load_from_toml => profile_load + operator(==) => serializable_is_same + serializable_is_same => profile_same @@ -697,7 +697,7 @@

    Arguments

    @@ -712,7 +712,7 @@

    Arguments

    @@ -757,7 +757,7 @@

    Arguments

    @@ -847,7 +847,7 @@

    Arguments

    @@ -862,7 +862,7 @@

    Arguments

    @@ -892,7 +892,7 @@

    Arguments

    @@ -1057,7 +1057,7 @@

    Arguments

    @@ -1072,7 +1072,7 @@

    Arguments

    @@ -1122,7 +1122,7 @@

    Arguments

    @@ -1137,7 +1137,7 @@

    Arguments

    @@ -1152,7 +1152,7 @@

    Arguments

    @@ -1192,7 +1192,7 @@

    Arguments

    @@ -1207,7 +1207,7 @@

    Arguments

    @@ -1222,7 +1222,7 @@

    Arguments

    @@ -1262,7 +1262,7 @@

    Arguments

    @@ -1277,7 +1277,7 @@

    Arguments

    @@ -1292,7 +1292,7 @@

    Arguments

    @@ -1378,7 +1378,7 @@

    Arguments

    @@ -1438,7 +1438,7 @@

    Arguments

    @@ -1453,7 +1453,7 @@

    Arguments

    @@ -1504,7 +1504,7 @@

    Arguments

    -

    public subroutine info(self, unit, verbosity) +

    public subroutine info(self, unit, verbosity)

    @@ -1523,7 +1523,7 @@

    Arguments

    @@ -1538,7 +1538,7 @@

    Arguments

    @@ -1553,7 +1553,7 @@

    Arguments

    @@ -1648,7 +1648,7 @@

    Arguments

    @@ -1663,7 +1663,7 @@

    Arguments

    @@ -1678,7 +1678,7 @@

    Arguments

    @@ -1718,7 +1718,7 @@

    Arguments

    @@ -1733,7 +1733,7 @@

    Arguments

    @@ -1748,7 +1748,7 @@

    Arguments

    @@ -1788,7 +1788,7 @@

    Arguments

    @@ -1803,7 +1803,7 @@

    Arguments

    @@ -1818,7 +1818,7 @@

    Arguments

    @@ -1858,7 +1858,7 @@

    Arguments

    @@ -1888,7 +1888,7 @@

    Arguments

    @@ -1903,7 +1903,7 @@

    Arguments

    @@ -1933,7 +1933,7 @@

    Arguments

    @@ -1988,7 +1988,7 @@

    Arguments

    @@ -2033,7 +2033,7 @@

    Arguments

    @@ -2048,7 +2048,7 @@

    Arguments

    @@ -2078,7 +2078,7 @@

    Arguments

    @@ -2118,7 +2118,7 @@

    Arguments

    @@ -2163,7 +2163,7 @@

    Arguments

    @@ -2193,7 +2193,7 @@

    Arguments

    @@ -2343,7 +2343,7 @@

    Arguments

    @@ -2388,7 +2388,7 @@

    Arguments

    @@ -2403,7 +2403,7 @@

    Arguments

    @@ -2461,7 +2461,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_manifest_test.html b/module/fpm_manifest_test.html index 91f5f5b150..a076a57d38 100644 --- a/module/fpm_manifest_test.html +++ b/module/fpm_manifest_test.html @@ -175,10 +175,10 @@

    Uses

    @@ -237,7 +237,7 @@

    Components

    @@ -271,7 +271,7 @@

    Components

    @@ -288,7 +288,7 @@

    Components

    @@ -314,7 +314,7 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit @@ -329,7 +329,7 @@

    Type-Bound Procedures

    + load => load_from_toml, load_from_file, load_from_unit @@ -339,7 +339,7 @@

    Type-Bound Procedures

    + operator(==) => serializable_is_same @@ -383,7 +383,7 @@

    Arguments

    @@ -398,7 +398,7 @@

    Arguments

    @@ -413,7 +413,7 @@

    Arguments

    @@ -456,7 +456,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_meta.html b/module/fpm_meta.html index 5b2fc6f6b0..38ee03fc5c 100644 --- a/module/fpm_meta.html +++ b/module/fpm_meta.html @@ -188,22 +188,22 @@

    Uses

    @@ -245,7 +245,7 @@

    Arguments

    @@ -260,7 +260,7 @@

    Arguments

    @@ -275,7 +275,7 @@

    Arguments

    @@ -290,7 +290,7 @@

    Arguments

    @@ -376,7 +376,7 @@

    Components

    @@ -394,7 +394,7 @@

    Components

    @@ -428,7 +428,7 @@

    Components

    @@ -445,7 +445,7 @@

    Components

    @@ -649,7 +649,7 @@

    Components

    @@ -700,7 +700,7 @@

    Components

    @@ -726,7 +726,7 @@

    Type-Bound Procedures

    + destroy @@ -736,7 +736,7 @@

    Type-Bound Procedures

    + resolve => resolve_cmd, resolve_model, resolve_package_config @@ -818,7 +818,7 @@

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_model.html b/module/fpm_model.html index 18c22fb859..94dc152d9c 100644 --- a/module/fpm_model.html +++ b/module/fpm_model.html @@ -165,6 +165,7 @@

    Functions

    @@ -228,12 +229,12 @@

    Uses

    @@ -548,7 +549,7 @@

    Components

    @@ -565,7 +566,7 @@

    Components

    @@ -591,32 +592,32 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml => fft_dump_to_toml + load => load_from_toml, load_from_file, load_from_unit + load_from_toml => fft_load_from_toml + operator(==) => serializable_is_same + serializable_is_same => fft_is_same @@ -655,7 +656,7 @@

    Components

    @@ -706,7 +707,7 @@

    Components

    @@ -740,7 +741,7 @@

    Components

    @@ -757,7 +758,7 @@

    Components

    @@ -842,7 +843,7 @@

    Components

    @@ -936,32 +937,32 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml => model_dump_to_toml + load => load_from_toml, load_from_file, load_from_unit + load_from_toml => model_load_from_toml + operator(==) => serializable_is_same + serializable_is_same => model_is_same @@ -999,7 +1000,7 @@

    Components

    @@ -1050,7 +1051,7 @@

    Components

    @@ -1067,7 +1068,7 @@

    Components

    @@ -1084,7 +1085,7 @@

    Components

    @@ -1101,7 +1102,7 @@

    Components

    @@ -1127,32 +1128,32 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml => package_dump_to_toml + load => load_from_toml, load_from_file, load_from_unit + load_from_toml => package_load_from_toml + operator(==) => serializable_is_same + serializable_is_same => package_is_same @@ -1369,32 +1370,32 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml => srcfile_dump_to_toml + load => load_from_toml, load_from_file, load_from_unit + load_from_toml => srcfile_load_from_toml + operator(==) => serializable_is_same + serializable_is_same => srcfile_is_same @@ -1432,7 +1433,52 @@

    Arguments

    + + + + + + + +
    - + class(git_target_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + character(len=:), public,
    - + integer, public
    - + integer, public
    - + integer, public
    - + type(installer_t), intent(out)
    - + integer, intent(in),
    - + character(len=*), intent(in),
    - + type(example_config_t), intent(out)
    - + character(len=*), intent(in)
    - + type(executable_config_t), intent(out)
    - + character(len=*), intent(in)
    - + type(library_config_t), intent(out)
    - + type(test_config_t), intent(out)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + type(string_t), public,
    - + type(string_t), public,
    - + type(string_t), public
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => build_conf_is_same ../../

    Serialization interface

    - + type(build_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + type(dependency_config_t), intent(inout),
    - + integer, intent(in),
    - + character(len=:), public,
    - + character(len=:), public,
    - + type(preprocess_config_t), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => dependency_is_same ../../

    Serialization interface

    - + class(dependency_config_t), intent(in)
    - + class(dependency_config_t), intent(in)
    - + integer, intent(in)
    - + integer, intent(in)
    - + class(dependency_config_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + character(len=*), intent(in),
    - + type(metapackage_config_t), intent(out),
    - + type(error_t), intent(out),
    - + type(dependency_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + character(len=*), intent(in),
    - + type(error_t), intent(out),
    - + type(string_t), public,
    - + character(len=:), public,
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    generic, public :: - operator(==) => serializable_is_same
    - + type(example_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + type(string_t), public,
    - + character(len=:), public,
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    generic, public :: - operator(==) => serializable_is_same
    - + type(executable_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + logical, public
    - + logical, public
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => fortran_is_same ../../

    Serialization interface

    - + type(fortran_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => install_conf_same ../../

    Serialization interface

    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => library_is_same ../../

    Serialization interface

    - + type(library_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + type(metapackage_request_t), public
    - + character(len=:), public,
    - + character(len=:), public,
    - + type(metapackage_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + type(metapackage_request_t), intent(out)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + type(dependency_config_t), public,
    - + type(example_config_t), public,
    - + type(fortran_config_t), public
    - + type(metapackage_config_t), public
    - + character(len=:), public,
    - + type(preprocess_config_t), public,
    - + type(profile_config_t), public,
    - + type(test_config_t), public,
    - + type(version_t), public
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => manifest_is_same ../../

    Serialization interface

    - + type(package_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + character(len=*), intent(in),
    - + type(error_t), intent(out),
    - + character(len=:), public,
    - + type(string_t), public,
    procedure, public :: - destroy ../../

    Operations

    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => preprocess_is_same ../../

    Serialization interface

    - + type(preprocess_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => file_scope_dump
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => file_scope_load
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => file_scope_same ../../

    Serialization interface

    - + character(len=:), public,
    - + character(len=:), public,
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => profile_dump
    procedure, public :: - info ../../

    Print information on this instance

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => profile_load
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => profile_same ../../

    Serialization interface

    - + class(file_scope_flag), intent(in)
    - + class(serializable_t), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in),
    - + class(profile_config_t), intent(in)
    - + class(serializable_t), intent(in)
    - + class(file_scope_flag), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + class(file_scope_flag), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + type(profile_config_t), intent(in),
    - + character(len=:), intent(in),
    - + character(len=:), intent(in),
    - + character(len=:), intent(in),
    - + type(toml_table), intent(in),
    - + type(profile_config_t), intent(inout),
    - + class(profile_config_t), intent(in)
    - + integer, intent(in)
    - + integer, intent(in),
    - + type(profile_config_t), intent(out),
    - + type(toml_table), intent(inout),
    - + type(error_t), intent(out),
    - + class(profile_config_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + class(profile_config_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + character(len=:), intent(in),
    - + type(toml_table), intent(in),
    - + type(error_t), intent(out),
    - + type(profile_config_t), intent(inout),
    - + character(len=:), intent(in),
    - + type(toml_table), intent(in),
    - + type(profile_config_t), intent(inout),
    - + type(error_t), intent(out),
    - + character(len=:), intent(in),
    - + type(toml_table), intent(in),
    - + type(error_t), intent(out),
    - + character(len=:), intent(in),
    - + type(toml_table), intent(in),
    - + type(error_t), intent(out),
    - + type(string_t), public,
    - + character(len=:), public,
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    generic, public :: - operator(==) => serializable_is_same
    - + type(test_config_t), intent(out)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + type(fpm_model_t), intent(inout)
    - + type(package_config_t), intent(inout)
    - + class(fpm_build_settings), intent(inout)
    - + type(error_t), intent(out),
    - + type(dependency_config_t), public,
    - + type(string_t), public,
    - + type(string_t), public
    - + type(fortran_features_t), public,
    - + type(string_t), public
    - + type(version_t), public,
    procedure, public :: - destroy ../../

    Clean metapackage structure

    generic, public :: - resolve => resolve_cmd, resolve_model, resolve_package_config
    - + logical, public
    - + logical, public
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => fft_dump_to_toml
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => fft_load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => fft_is_same ../../

    Serialization interface

    - + type(archiver_t), public
    - + type(compiler_t), public
    - + type(dependency_tree_t), public
    - + logical, public
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => model_dump_to_toml
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => model_load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => model_is_same ../../

    Serialization interface

    - + logical, public
    - + character(len=:), public,
    - + type(preprocess_config_t), public
    - + type(srcfile_t), public,
    - + character(len=:), public,
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => package_dump_to_toml
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => package_load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => package_is_same ../../

    Serialization interface

    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure, public :: - dump_to_toml => srcfile_dump_to_toml
    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure, public :: - load_from_toml => srcfile_load_from_toml
    generic, public :: - operator(==) => serializable_is_same
    procedure, public :: - serializable_is_same => srcfile_is_same ../../

    Serialization interface

    - + + integer, + intent(in) + + ::flag + +
    + +

    + Return Value + character(len=:), allocatable +

    + + +
    +

    + +
    +

    public function FPM_UNIT_NAME(flag) result(name) +

    +
    + +

    Return the character name of a unit flag

    + +

    Arguments

    + + + + + + + + + + + + @@ -1482,7 +1528,7 @@

    Arguments

    @@ -1525,7 +1571,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_os.html b/module/fpm_os.html index 83505a1ce2..afd0516996 100644 --- a/module/fpm_os.html +++ b/module/fpm_os.html @@ -157,9 +157,9 @@

    Uses

    @@ -214,7 +214,7 @@

    Arguments

    @@ -254,7 +254,7 @@

    Arguments

    @@ -269,7 +269,7 @@

    Arguments

    @@ -310,7 +310,7 @@

    Arguments

    @@ -340,7 +340,7 @@

    Arguments

    @@ -380,7 +380,7 @@

    Arguments

    @@ -410,7 +410,7 @@

    Arguments

    @@ -450,7 +450,7 @@

    Arguments

    @@ -465,7 +465,7 @@

    Arguments

    @@ -508,7 +508,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_pkg_config.html b/module/fpm_pkg_config.html index 4d28f21da9..a87b2232d2 100644 --- a/module/fpm_pkg_config.html +++ b/module/fpm_pkg_config.html @@ -171,9 +171,9 @@

    Uses

  • @@ -231,7 +231,7 @@

    Arguments

    @@ -262,7 +262,7 @@

    Arguments

    @@ -307,7 +307,7 @@

    Arguments

    @@ -322,7 +322,7 @@

    Arguments

    @@ -367,7 +367,7 @@

    Arguments

    @@ -382,7 +382,7 @@

    Arguments

    @@ -427,7 +427,7 @@

    Arguments

    @@ -472,7 +472,7 @@

    Arguments

    @@ -567,7 +567,7 @@

    Arguments

    @@ -655,7 +655,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_release.html b/module/fpm_release.html index b066a84727..79af21724d 100644 --- a/module/fpm_release.html +++ b/module/fpm_release.html @@ -154,8 +154,8 @@

    Uses

    @@ -215,7 +215,7 @@

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_settings.html b/module/fpm_settings.html index a3de75ca70..f26305961a 100644 --- a/module/fpm_settings.html +++ b/module/fpm_settings.html @@ -177,8 +177,8 @@

    Uses

  • @@ -375,7 +375,7 @@

    Arguments

  • @@ -415,7 +415,7 @@

    Arguments

    @@ -445,7 +445,7 @@

    Arguments

    @@ -488,7 +488,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_source_parsing.html b/module/fpm_source_parsing.html index 24e89cbea7..f4a2dbe990 100644 --- a/module/fpm_source_parsing.html +++ b/module/fpm_source_parsing.html @@ -176,10 +176,10 @@

    Uses

    @@ -232,7 +232,7 @@

    Arguments

    @@ -292,7 +292,7 @@

    Arguments

    @@ -357,7 +357,7 @@

    Arguments

    @@ -372,7 +372,7 @@

    Arguments

    @@ -417,7 +417,7 @@

    Arguments

    @@ -432,7 +432,7 @@

    Arguments

    @@ -475,7 +475,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_sources.html b/module/fpm_sources.html index 21080ad196..b0c75174eb 100644 --- a/module/fpm_sources.html +++ b/module/fpm_sources.html @@ -168,11 +168,11 @@

    Uses

  • @@ -211,7 +211,7 @@

    Arguments

    @@ -264,7 +264,7 @@

    Arguments

    @@ -294,7 +294,7 @@

    Arguments

    @@ -339,7 +339,7 @@

    Arguments

    @@ -379,7 +379,7 @@

    Arguments

    @@ -409,7 +409,7 @@

    Arguments

    @@ -454,7 +454,7 @@

    Arguments

    @@ -469,7 +469,7 @@

    Arguments

    @@ -512,7 +512,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_strings.html b/module/fpm_strings.html index 921f94f503..217736740d 100644 --- a/module/fpm_strings.html +++ b/module/fpm_strings.html @@ -127,7 +127,7 @@

    Interfaces

    len_trimoperator(.in.)operator(==) - resize + resizestrstr_ends_withstring_t @@ -251,7 +251,7 @@

    Miscellaneous

    • fnv_1a Hash a CHARACTER(*) string of default kind or a TYPE(STRING_T) array
    • replace Returns string with characters in charset replaced with target_char.
    • -
    • resize increase the size of a TYPE(STRING_T) array by N elements
    • +
    • resize increase the size of a TYPE(STRING_T) array by N elements

    Module naming

    License: Public Domain @@ -271,8 +271,8 @@

    Uses

    @@ -314,7 +314,7 @@

    Arguments

    @@ -372,7 +372,7 @@

    Arguments

    @@ -440,7 +440,7 @@

    Arguments

    @@ -605,7 +605,7 @@

    Arguments

    @@ -620,7 +620,7 @@

    Arguments

    @@ -663,7 +663,7 @@

    Arguments

    @@ -678,7 +678,7 @@

    Arguments

    @@ -706,8 +706,8 @@

    - -

    public interface resize + +

    public interface resize

      @@ -731,7 +731,7 @@

      Arguments

    @@ -746,7 +746,7 @@

    Arguments

    @@ -794,7 +794,7 @@

    Arguments

    @@ -837,7 +837,7 @@

    Arguments

    @@ -880,7 +880,7 @@

    Arguments

    @@ -933,7 +933,7 @@

    Arguments

    @@ -991,7 +991,7 @@

    Arguments

    @@ -1049,7 +1049,7 @@

    Arguments

    @@ -1118,7 +1118,7 @@

    Arguments

    @@ -1175,7 +1175,7 @@

    Components

    @@ -1405,7 +1405,7 @@

    Arguments

    @@ -1468,7 +1468,7 @@

    Arguments

    @@ -1483,7 +1483,7 @@

    Arguments

    @@ -1528,7 +1528,7 @@

    Arguments

    @@ -1576,7 +1576,7 @@

    Arguments

    @@ -1591,7 +1591,7 @@

    Arguments

    @@ -1621,7 +1621,7 @@

    Arguments

    @@ -1668,7 +1668,7 @@

    Arguments

    @@ -1735,7 +1735,7 @@

    Arguments

    @@ -2054,7 +2054,7 @@

    Arguments

    @@ -2129,7 +2129,7 @@

    Arguments

    @@ -2327,7 +2327,7 @@

    Arguments

    @@ -2527,7 +2527,7 @@

    Arguments

    @@ -2597,7 +2597,7 @@

    Arguments

    @@ -2742,7 +2742,7 @@

    Arguments

    @@ -2830,7 +2830,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_targets.html b/module/fpm_targets.html index 941c32fef3..fc851b1e1f 100644 --- a/module/fpm_targets.html +++ b/module/fpm_targets.html @@ -217,15 +217,15 @@

    Uses

    @@ -386,7 +386,7 @@

    Components

    @@ -639,7 +639,7 @@

    Components

    @@ -707,7 +707,7 @@

    Components

    @@ -758,7 +758,7 @@

    Components

    @@ -882,7 +882,7 @@

    Arguments

    @@ -922,7 +922,7 @@

    Arguments

    @@ -937,7 +937,7 @@

    Arguments

    @@ -982,7 +982,7 @@

    Arguments

    @@ -1027,7 +1027,7 @@

    Arguments

    @@ -1042,7 +1042,7 @@

    Arguments

    @@ -1082,7 +1082,7 @@

    Arguments

    @@ -1112,7 +1112,7 @@

    Arguments

    @@ -1152,7 +1152,7 @@

    Arguments

    @@ -1167,7 +1167,7 @@

    Arguments

    @@ -1207,7 +1207,7 @@

    Arguments

    @@ -1222,7 +1222,7 @@

    Arguments

    @@ -1263,7 +1263,7 @@

    Arguments

    @@ -1278,7 +1278,7 @@

    Arguments

    @@ -1293,7 +1293,7 @@

    Arguments

    @@ -1333,7 +1333,7 @@

    Arguments

    @@ -1348,7 +1348,7 @@

    Arguments

    @@ -1378,7 +1378,7 @@

    Arguments

    @@ -1421,7 +1421,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_toml.html b/module/fpm_toml.html index c1502fb389..5ffd6fade0 100644 --- a/module/fpm_toml.html +++ b/module/fpm_toml.html @@ -203,10 +203,10 @@

    Uses

  • @@ -253,7 +253,7 @@

    Arguments

    @@ -283,7 +283,7 @@

    Arguments

    @@ -298,7 +298,7 @@

    Arguments

    @@ -364,7 +364,7 @@

    Arguments

    @@ -394,7 +394,7 @@

    Arguments

    @@ -409,7 +409,7 @@

    Arguments

    @@ -462,7 +462,7 @@

    Arguments

    @@ -492,7 +492,7 @@

    Arguments

    @@ -507,7 +507,7 @@

    Arguments

    @@ -560,7 +560,7 @@

    Arguments

    @@ -590,7 +590,7 @@

    Arguments

    @@ -605,7 +605,7 @@

    Arguments

    @@ -669,7 +669,7 @@

    Arguments

    @@ -699,7 +699,7 @@

    Arguments

    @@ -714,7 +714,7 @@

    Arguments

    @@ -767,7 +767,7 @@

    Arguments

    @@ -797,7 +797,7 @@

    Arguments

    @@ -812,7 +812,7 @@

    Arguments

    @@ -878,7 +878,7 @@

    Arguments

    @@ -908,7 +908,7 @@

    Arguments

    @@ -923,7 +923,7 @@

    Arguments

    @@ -976,7 +976,7 @@

    Arguments

    @@ -1006,7 +1006,7 @@

    Arguments

    @@ -1021,7 +1021,7 @@

    Arguments

    @@ -1074,7 +1074,7 @@

    Arguments

    @@ -1104,7 +1104,7 @@

    Arguments

    @@ -1119,7 +1119,7 @@

    Arguments

    @@ -1181,32 +1181,32 @@

    Type-Bound Procedures

    + dump => dump_to_toml, dump_to_file, dump_to_unit + dump_to_toml + load => load_from_toml, load_from_file, load_from_unit + load_from_toml + operator(==) => serializable_is_same + serializable_is_same @@ -1295,7 +1295,7 @@

    Arguments

    @@ -1310,7 +1310,7 @@

    Arguments

    @@ -1325,7 +1325,7 @@

    Arguments

    @@ -1365,7 +1365,7 @@

    Arguments

    @@ -1395,7 +1395,7 @@

    Arguments

    @@ -1410,7 +1410,7 @@

    Arguments

    @@ -1450,7 +1450,7 @@

    Arguments

    @@ -1465,7 +1465,7 @@

    Arguments

    @@ -1480,7 +1480,7 @@

    Arguments

    @@ -1520,7 +1520,7 @@

    Arguments

    @@ -1550,7 +1550,7 @@

    Arguments

    @@ -1565,7 +1565,7 @@

    Arguments

    @@ -1608,7 +1608,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/module/fpm_versioning.html b/module/fpm_versioning.html index 80ce72b205..0f990a4f74 100644 --- a/module/fpm_versioning.html +++ b/module/fpm_versioning.html @@ -175,9 +175,9 @@

    Uses

    @@ -219,7 +219,7 @@

    Arguments

    @@ -234,7 +234,7 @@

    Arguments

    @@ -249,7 +249,7 @@

    Arguments

    @@ -287,7 +287,7 @@

    Arguments

    @@ -302,7 +302,7 @@

    Arguments

    @@ -369,7 +369,7 @@

    Type-Bound Procedures

    + operator(==) => equals @@ -384,7 +384,7 @@

    Type-Bound Procedures

    + s @@ -447,7 +447,7 @@

    Arguments

    @@ -496,7 +496,7 @@

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/page/Contributing.html b/page/Contributing.html index 2d93cd1796..5eff6c871e 100644 --- a/page/Contributing.html +++ b/page/Contributing.html @@ -229,7 +229,7 @@

    For new contributors

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/page/License.html b/page/License.html index 90e2f3d5c6..facd365efd 100644 --- a/page/License.html +++ b/page/License.html @@ -138,7 +138,7 @@

    License

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/page/Manifest.html b/page/Manifest.html index ddf05e8c43..44f6f63afe 100644 --- a/page/Manifest.html +++ b/page/Manifest.html @@ -123,7 +123,7 @@

    301 - Moved

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/page/Packaging.html b/page/Packaging.html index f458230a3b..75e4e456d1 100644 --- a/page/Packaging.html +++ b/page/Packaging.html @@ -731,7 +731,7 @@

    Custom build scripts

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/page/index.html b/page/index.html index e74c00e326..ac2a7584d8 100644 --- a/page/index.html +++ b/page/index.html @@ -121,7 +121,7 @@

    Packaging and contributing

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/add_dependency.html b/proc/add_dependency.html index dc1d77515a..074a1edf2c 100644 --- a/proc/add_dependency.html +++ b/proc/add_dependency.html @@ -177,7 +177,7 @@

    Arguments

    @@ -237,7 +237,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/add_executable_sources.html b/proc/add_executable_sources.html index 344f18e261..c6abc88f68 100644 --- a/proc/add_executable_sources.html +++ b/proc/add_executable_sources.html @@ -165,7 +165,7 @@

    Arguments

    @@ -195,7 +195,7 @@

    Arguments

    @@ -240,7 +240,7 @@

    Arguments

    @@ -367,7 +367,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/add_sources_from_dir.html b/proc/add_sources_from_dir.html index 48e7de2bc4..0cac222431 100644 --- a/proc/add_sources_from_dir.html +++ b/proc/add_sources_from_dir.html @@ -162,7 +162,7 @@

    Arguments

    @@ -192,7 +192,7 @@

    Arguments

    @@ -237,7 +237,7 @@

    Arguments

    @@ -252,7 +252,7 @@

    Arguments

    @@ -385,7 +385,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/add_target.html b/proc/add_target.html index af5ae04396..daabb374b2 100644 --- a/proc/add_target.html +++ b/proc/add_target.html @@ -162,7 +162,7 @@

    Arguments

    @@ -177,7 +177,7 @@

    Arguments

    @@ -222,7 +222,7 @@

    Arguments

    @@ -267,7 +267,7 @@

    Arguments

    @@ -282,7 +282,7 @@

    Arguments

    @@ -382,7 +382,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/ar_is_same.html b/proc/ar_is_same.html index 85b2c0bc28..f4f2c80bfc 100644 --- a/proc/ar_is_same.html +++ b/proc/ar_is_same.html @@ -165,7 +165,7 @@

    Arguments

    @@ -180,7 +180,7 @@

    Arguments

    @@ -263,7 +263,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/assert_pkg_config.html b/proc/assert_pkg_config.html index c645ce20c9..e01fc178a1 100644 --- a/proc/assert_pkg_config.html +++ b/proc/assert_pkg_config.html @@ -208,7 +208,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/bad_name_error.html b/proc/bad_name_error.html index 43023b86a5..5ed7ac2616 100644 --- a/proc/bad_name_error.html +++ b/proc/bad_name_error.html @@ -161,7 +161,7 @@

    Arguments

    @@ -191,7 +191,7 @@

    Arguments

    @@ -274,7 +274,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/basename.html b/proc/basename.html index 4d5eee4808..fae37d4637 100644 --- a/proc/basename.html +++ b/proc/basename.html @@ -162,7 +162,7 @@

    Arguments

    @@ -266,7 +266,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/build_model.html b/proc/build_model.html index f88bfc0ef8..9b6d971a11 100644 --- a/proc/build_model.html +++ b/proc/build_model.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -194,7 +194,7 @@

    Arguments

    @@ -209,7 +209,7 @@

    Arguments

    @@ -485,7 +485,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/build_package.html b/proc/build_package.html index d35be87399..d7f381ba8c 100644 --- a/proc/build_package.html +++ b/proc/build_package.html @@ -177,7 +177,7 @@

    Arguments

    @@ -192,7 +192,7 @@

    Arguments

    @@ -350,7 +350,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/canon_path.html b/proc/canon_path.html index 16c72246ec..b9495fbe24 100644 --- a/proc/canon_path.html +++ b/proc/canon_path.html @@ -166,7 +166,7 @@

    Arguments

    @@ -318,7 +318,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/change_directory.html b/proc/change_directory.html index d1c770ec84..7f43a8e559 100644 --- a/proc/change_directory.html +++ b/proc/change_directory.html @@ -161,7 +161,7 @@

    Arguments

    @@ -176,7 +176,7 @@

    Arguments

    @@ -245,7 +245,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/check_and_read_pkg_data.html b/proc/check_and_read_pkg_data.html index e1ad27ebd8..fe4beca811 100644 --- a/proc/check_and_read_pkg_data.html +++ b/proc/check_and_read_pkg_data.html @@ -170,7 +170,7 @@

    Arguments

    @@ -215,7 +215,7 @@

    Arguments

    @@ -262,7 +262,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/check_compiler.html b/proc/check_compiler.html index 834e2f8655..3da3e8a7dd 100644 --- a/proc/check_compiler.html +++ b/proc/check_compiler.html @@ -161,7 +161,7 @@

    Arguments

    @@ -245,7 +245,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/check_fortran_source_runs.html b/proc/check_fortran_source_runs.html index 2657fd5761..a3249d06c9 100644 --- a/proc/check_fortran_source_runs.html +++ b/proc/check_fortran_source_runs.html @@ -121,7 +121,7 @@

    Variables

    logfobjectsource - stat + statunit @@ -187,7 +187,7 @@

    Arguments

    @@ -202,7 +202,7 @@

    Arguments

    @@ -220,7 +220,7 @@

    Arguments

    Return Value - + logical

    @@ -310,7 +310,7 @@

    Variables

    @@ -427,7 +427,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/check_keys.html b/proc/check_keys.html index a2f4e5d1e7..18a2d31d83 100644 --- a/proc/check_keys.html +++ b/proc/check_keys.html @@ -163,7 +163,7 @@

    Arguments

    @@ -178,7 +178,7 @@

    Arguments

    @@ -193,7 +193,7 @@

    Arguments

    @@ -295,7 +295,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/check_modules_for_duplicates.html b/proc/check_modules_for_duplicates.html index b721d1089b..faddfda283 100644 --- a/proc/check_modules_for_duplicates.html +++ b/proc/check_modules_for_duplicates.html @@ -161,7 +161,7 @@

    Arguments

    @@ -271,7 +271,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/checkout.html b/proc/checkout.html index 40d473d356..610ecf8913 100644 --- a/proc/checkout.html +++ b/proc/checkout.html @@ -117,8 +117,8 @@

    Variables

    @@ -176,7 +176,7 @@

    Arguments

    @@ -206,7 +206,7 @@

    Arguments

    @@ -239,7 +239,7 @@

    Variables

    @@ -256,7 +256,7 @@

    Variables

    @@ -371,7 +371,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/cmd_build.html b/proc/cmd_build.html index 27dd7dd933..982273ed35 100644 --- a/proc/cmd_build.html +++ b/proc/cmd_build.html @@ -162,7 +162,7 @@

    Arguments

    @@ -257,7 +257,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/cmd_clean.html b/proc/cmd_clean.html index 8ba5023c18..5cce56a20d 100644 --- a/proc/cmd_clean.html +++ b/proc/cmd_clean.html @@ -163,7 +163,7 @@

    Arguments

    @@ -249,7 +249,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/cmd_export.html b/proc/cmd_export.html index 919f7db814..5af0e82323 100644 --- a/proc/cmd_export.html +++ b/proc/cmd_export.html @@ -168,7 +168,7 @@

    Arguments

    @@ -277,7 +277,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/cmd_install.html b/proc/cmd_install.html index e7689a08a3..33cff09775 100644 --- a/proc/cmd_install.html +++ b/proc/cmd_install.html @@ -162,7 +162,7 @@

    Arguments

    @@ -274,7 +274,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/cmd_new.html b/proc/cmd_new.html index 26ee900890..3a7c2fd5ad 100644 --- a/proc/cmd_new.html +++ b/proc/cmd_new.html @@ -164,7 +164,7 @@

    Arguments

    @@ -848,7 +848,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/cmd_publish.html b/proc/cmd_publish.html index c4ed89db33..377989ed24 100644 --- a/proc/cmd_publish.html +++ b/proc/cmd_publish.html @@ -77,7 +77,7 @@

    cmd_publish
  • 61 statements + title=" 0.9% of total for procedures.">61 statements
  • @@ -158,7 +158,7 @@

    Arguments

  • @@ -205,7 +205,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/cmd_run.html b/proc/cmd_run.html index a64174904a..1e6efd9c35 100644 --- a/proc/cmd_run.html +++ b/proc/cmd_run.html @@ -161,7 +161,7 @@

    Arguments

    @@ -176,7 +176,7 @@

    Arguments

    @@ -418,7 +418,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/cmd_update.html b/proc/cmd_update.html index 01b00d3ddf..b5f70c47dd 100644 --- a/proc/cmd_update.html +++ b/proc/cmd_update.html @@ -162,7 +162,7 @@

    Arguments

    @@ -267,7 +267,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/compile_c.html b/proc/compile_c.html index 86ce444f7e..edb85d85ea 100644 --- a/proc/compile_c.html +++ b/proc/compile_c.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -194,7 +194,7 @@

    Arguments

    @@ -239,7 +239,7 @@

    Arguments

    @@ -309,7 +309,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/compile_cpp.html b/proc/compile_cpp.html index e309cb5f22..3efbdf5d1f 100644 --- a/proc/compile_cpp.html +++ b/proc/compile_cpp.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -194,7 +194,7 @@

    Arguments

    @@ -239,7 +239,7 @@

    Arguments

    @@ -309,7 +309,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/compile_fortran.html b/proc/compile_fortran.html index 094a29a4bd..6ca2aba53d 100644 --- a/proc/compile_fortran.html +++ b/proc/compile_fortran.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -194,7 +194,7 @@

    Arguments

    @@ -239,7 +239,7 @@

    Arguments

    @@ -309,7 +309,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/compiler_dump.html b/proc/compiler_dump.html index 5efc8f85f8..1f8bdaa3e0 100644 --- a/proc/compiler_dump.html +++ b/proc/compiler_dump.html @@ -117,7 +117,7 @@

    Variables

    - ierr + ierr
    @@ -175,7 +175,7 @@

    Arguments

    @@ -190,7 +190,7 @@

    Arguments

    @@ -205,7 +205,7 @@

    Arguments

    @@ -238,7 +238,7 @@

    Variables

    @@ -319,7 +319,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/compiler_is_same.html b/proc/compiler_is_same.html index b1239dc7ab..4fad9a48ea 100644 --- a/proc/compiler_is_same.html +++ b/proc/compiler_is_same.html @@ -165,7 +165,7 @@

    Arguments

    @@ -180,7 +180,7 @@

    Arguments

    @@ -265,7 +265,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/compiler_load.html b/proc/compiler_load.html index 99ef18ba25..cb9f065a44 100644 --- a/proc/compiler_load.html +++ b/proc/compiler_load.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -194,7 +194,7 @@

    Arguments

    @@ -269,7 +269,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/compiler_name.html b/proc/compiler_name.html index 5d19d28b77..47089db2bc 100644 --- a/proc/compiler_name.html +++ b/proc/compiler_name.html @@ -164,7 +164,7 @@

    Arguments

    @@ -182,7 +182,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -253,7 +253,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/convert_to_absolute_path.html b/proc/convert_to_absolute_path.html index a174644b0c..684e37ce92 100644 --- a/proc/convert_to_absolute_path.html +++ b/proc/convert_to_absolute_path.html @@ -156,7 +156,7 @@

    Arguments

    @@ -171,7 +171,7 @@

    Arguments

    @@ -218,7 +218,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/debug_archiver.html b/proc/debug_archiver.html index 50fba4647b..29952c1882 100644 --- a/proc/debug_archiver.html +++ b/proc/debug_archiver.html @@ -162,7 +162,7 @@

    Arguments

    @@ -230,7 +230,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/debug_compiler.html b/proc/debug_compiler.html index 1506dfea42..4e194c6880 100644 --- a/proc/debug_compiler.html +++ b/proc/debug_compiler.html @@ -162,7 +162,7 @@

    Arguments

    @@ -230,7 +230,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/default_example.html b/proc/default_example.html index e268dc48b1..bacf8aa0f2 100644 --- a/proc/default_example.html +++ b/proc/default_example.html @@ -162,7 +162,7 @@

    Arguments

    @@ -177,7 +177,7 @@

    Arguments

    @@ -243,7 +243,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/default_executable.html b/proc/default_executable.html index 866b9588d4..b1ed727474 100644 --- a/proc/default_executable.html +++ b/proc/default_executable.html @@ -162,7 +162,7 @@

    Arguments

    @@ -177,7 +177,7 @@

    Arguments

    @@ -243,7 +243,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/default_library.html b/proc/default_library.html index 557e5e941a..dc53e6135c 100644 --- a/proc/default_library.html +++ b/proc/default_library.html @@ -162,7 +162,7 @@

    Arguments

    @@ -224,7 +224,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/default_test.html b/proc/default_test.html index 27824d133a..a889edfcbf 100644 --- a/proc/default_test.html +++ b/proc/default_test.html @@ -162,7 +162,7 @@

    Arguments

    @@ -177,7 +177,7 @@

    Arguments

    @@ -243,7 +243,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/delete_env.html b/proc/delete_env.html index 21d4b4d475..35722ccfb8 100644 --- a/proc/delete_env.html +++ b/proc/delete_env.html @@ -165,7 +165,7 @@

    Arguments

    @@ -183,7 +183,7 @@

    Arguments

    Return Value - + logical

    @@ -253,7 +253,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/delete_file.html b/proc/delete_file.html index 5dd8e897fd..cacf1b2c2d 100644 --- a/proc/delete_file.html +++ b/proc/delete_file.html @@ -162,7 +162,7 @@

    Arguments

    @@ -225,7 +225,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/dependency_destroy.html b/proc/dependency_destroy.html index c08ff64dbd..3d27b26c28 100644 --- a/proc/dependency_destroy.html +++ b/proc/dependency_destroy.html @@ -162,7 +162,7 @@

    Arguments

    @@ -225,7 +225,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/descriptor_name.html b/proc/descriptor_name.html index 9de10d6efd..414b5cb20d 100644 --- a/proc/descriptor_name.html +++ b/proc/descriptor_name.html @@ -180,7 +180,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -235,7 +235,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/destroy_dependency_node.html b/proc/destroy_dependency_node.html index 29fd777638..8508d2a787 100644 --- a/proc/destroy_dependency_node.html +++ b/proc/destroy_dependency_node.html @@ -162,7 +162,7 @@

    Arguments

    @@ -231,7 +231,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/dilate.html b/proc/dilate.html index 97d05c6aac..b6d4a198a0 100644 --- a/proc/dilate.html +++ b/proc/dilate.html @@ -283,7 +283,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/dirname.html b/proc/dirname.html index fc08ce7bc5..46e52b661d 100644 --- a/proc/dirname.html +++ b/proc/dirname.html @@ -162,7 +162,7 @@

    Arguments

    @@ -180,7 +180,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -229,7 +229,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/dump_to_toml~3.html b/proc/dump_to_toml~4.html similarity index 97% rename from proc/dump_to_toml~3.html rename to proc/dump_to_toml~4.html index 0641e5c2f6..ade15178e3 100644 --- a/proc/dump_to_toml~3.html +++ b/proc/dump_to_toml~4.html @@ -117,7 +117,7 @@

    Variables

    - ierr + ierr
    @@ -143,7 +143,7 @@

    Variables

    Source Code

    @@ -175,7 +175,7 @@

    Arguments

    @@ -190,7 +190,7 @@

    Arguments

    @@ -205,7 +205,7 @@

    Arguments

    @@ -238,7 +238,7 @@

    Variables

    @@ -313,7 +313,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/dump_to_toml~8.html b/proc/dump_to_toml~9.html similarity index 97% rename from proc/dump_to_toml~8.html rename to proc/dump_to_toml~9.html index 93ba93af90..cdd38acd17 100644 --- a/proc/dump_to_toml~8.html +++ b/proc/dump_to_toml~9.html @@ -132,7 +132,7 @@

    Contents

    Source Code

    @@ -165,7 +165,7 @@

    Arguments

    @@ -180,7 +180,7 @@

    Arguments

    @@ -195,7 +195,7 @@

    Arguments

    @@ -270,7 +270,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/enumerate_libraries.html b/proc/enumerate_libraries.html index 30831d701e..92efc1ce30 100644 --- a/proc/enumerate_libraries.html +++ b/proc/enumerate_libraries.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -194,7 +194,7 @@

    Arguments

    @@ -212,7 +212,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -267,7 +267,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/execute_and_read_output.html b/proc/execute_and_read_output.html index b2f48b97c3..479e083067 100644 --- a/proc/execute_and_read_output.html +++ b/proc/execute_and_read_output.html @@ -156,7 +156,7 @@

    Arguments

    @@ -171,7 +171,7 @@

    Arguments

    @@ -186,7 +186,7 @@

    Arguments

    @@ -201,7 +201,7 @@

    Arguments

    @@ -248,7 +248,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/exists.html b/proc/exists.html index decebe94b3..0f518caa81 100644 --- a/proc/exists.html +++ b/proc/exists.html @@ -156,7 +156,7 @@

    Arguments

    @@ -174,7 +174,7 @@

    Arguments

    Return Value - + logical

    @@ -210,7 +210,7 @@

    Return Value

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/f_string.html b/proc/f_string.html index a0aebc526e..99c2cfadc2 100644 --- a/proc/f_string.html +++ b/proc/f_string.html @@ -254,7 +254,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/fatal_error.html b/proc/fatal_error.html index 182c271b06..2cdf81aa82 100644 --- a/proc/fatal_error.html +++ b/proc/fatal_error.html @@ -162,7 +162,7 @@

    Arguments

    @@ -177,7 +177,7 @@

    Arguments

    @@ -242,7 +242,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/file_not_found_error.html b/proc/file_not_found_error.html index b48b1e3b8d..d2b9e95e95 100644 --- a/proc/file_not_found_error.html +++ b/proc/file_not_found_error.html @@ -162,7 +162,7 @@

    Arguments

    @@ -242,7 +242,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/file_parse_error.html b/proc/file_parse_error.html index 164db9bf68..ecb92d0a91 100644 --- a/proc/file_parse_error.html +++ b/proc/file_parse_error.html @@ -162,7 +162,7 @@

    Arguments

    @@ -192,7 +192,7 @@

    Arguments

    @@ -356,7 +356,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/file_scope_dump.html b/proc/file_scope_dump.html index 09edddbca0..c3e4c02045 100644 --- a/proc/file_scope_dump.html +++ b/proc/file_scope_dump.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -194,7 +194,7 @@

    Arguments

    @@ -264,7 +264,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/file_scope_load.html b/proc/file_scope_load.html index 45a0d0ae2f..18226584ca 100644 --- a/proc/file_scope_load.html +++ b/proc/file_scope_load.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -194,7 +194,7 @@

    Arguments

    @@ -262,7 +262,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/file_scope_same.html b/proc/file_scope_same.html index 7c3b741cbf..8c6e5eccd5 100644 --- a/proc/file_scope_same.html +++ b/proc/file_scope_same.html @@ -164,7 +164,7 @@

    Arguments

    @@ -179,7 +179,7 @@

    Arguments

    @@ -265,7 +265,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/fileclose.html b/proc/fileclose.html index 5e6521f6e0..fe6cfe4547 100644 --- a/proc/fileclose.html +++ b/proc/fileclose.html @@ -162,7 +162,7 @@

    Arguments

    @@ -246,7 +246,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/fileopen.html b/proc/fileopen.html index 4f36181bb7..93d6e05dc0 100644 --- a/proc/fileopen.html +++ b/proc/fileopen.html @@ -162,7 +162,7 @@

    Arguments

    @@ -177,7 +177,7 @@

    Arguments

    @@ -279,7 +279,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/filewrite.html b/proc/filewrite.html index 4e021b4727..95e6f5f0c3 100644 --- a/proc/filewrite.html +++ b/proc/filewrite.html @@ -162,7 +162,7 @@

    Arguments

    @@ -251,7 +251,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/filter_executable_targets.html b/proc/filter_executable_targets.html index 050a3ab30b..a65fc0a975 100644 --- a/proc/filter_executable_targets.html +++ b/proc/filter_executable_targets.html @@ -161,7 +161,7 @@

    Arguments

    @@ -191,7 +191,7 @@

    Arguments

    @@ -262,7 +262,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/filter_library_targets.html b/proc/filter_library_targets.html index d201fd312b..2c5630e443 100644 --- a/proc/filter_library_targets.html +++ b/proc/filter_library_targets.html @@ -161,7 +161,7 @@

    Arguments

    @@ -176,7 +176,7 @@

    Arguments

    @@ -246,7 +246,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/filter_modules.html b/proc/filter_modules.html index bec8ae844b..33b944896b 100644 --- a/proc/filter_modules.html +++ b/proc/filter_modules.html @@ -161,7 +161,7 @@

    Arguments

    @@ -176,7 +176,7 @@

    Arguments

    @@ -251,7 +251,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/find_profile.html b/proc/find_profile.html index 417960abb3..1f9000a840 100644 --- a/proc/find_profile.html +++ b/proc/find_profile.html @@ -121,7 +121,7 @@

    Variables

    curr_oscurr_prioritycurr_profile_name - i + ipriority @@ -178,7 +178,7 @@

    Arguments

    @@ -193,7 +193,7 @@

    Arguments

    @@ -208,7 +208,7 @@

    Arguments

    @@ -354,7 +354,7 @@

    Variables

    @@ -483,7 +483,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/fpm_scope_name.html b/proc/fpm_scope_name.html index 438f529821..3045ef611f 100644 --- a/proc/fpm_scope_name.html +++ b/proc/fpm_scope_name.html @@ -162,7 +162,7 @@

    Arguments

    @@ -180,7 +180,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -236,7 +236,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/fpm_stop.html b/proc/fpm_stop.html index 661c77bc9f..e98f9eab55 100644 --- a/proc/fpm_stop.html +++ b/proc/fpm_stop.html @@ -176,7 +176,7 @@

    Arguments

    @@ -251,7 +251,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/fpm_target_name.html b/proc/fpm_target_name.html index 4d96564787..52cbc28e9b 100644 --- a/proc/fpm_target_name.html +++ b/proc/fpm_target_name.html @@ -236,7 +236,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/fpm_unit_name.html b/proc/fpm_unit_name.html new file mode 100644 index 0000000000..5a4a31625a --- /dev/null +++ b/proc/fpm_unit_name.html @@ -0,0 +1,270 @@ + + + + + + + + + + + + + FPM_UNIT_NAME – Fortran-lang/fpm + + + + + + + + + + + + + + +
    + +
    + +
    +
    +

    FPM_UNIT_NAME + Function + +

    +
    +
    +
    + +
    +
    + +
    +
    +
    + + +
    + +
    + + +
    +

    public function FPM_UNIT_NAME(flag) result(name) +

    + + +

    Return the character name of a unit flag

    + + +

    Arguments

    +
    TypeIntentOptional AttributesName
    + integer, intent(in)
    - + type(fpm_model_t), intent(in)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=:), intent(inout),
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=:), intent(out),
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + logical, intent(in),
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout),
    - + type(error_t), intent(out),
    - + type(error_t), intent(out),
    - + type(error_t), intent(out),
    - + integer, intent(in)
    - + character(len=*), intent(in)
    - + character(len=:), intent(out),
    - + type(error_t), intent(out),
    - + type(srcfile_t), intent(in)
    - + type(srcfile_t), intent(inout),
    - + integer, intent(in)
    - + type(error_t), intent(out),
    - + type(srcfile_t), intent(inout),
    - + integer, intent(in)
    - + logical, intent(in),
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(string_t), intent(in)
    - + type(string_t), intent(in)
    - + type(string_t), intent(in)
    - + type(string_t), intent(in)
    - + type(string_t), intent(in),
    - + type(string_t), intent(in),
    - + type(string_t), intent(inout),
    - + integer, intent(in),
    - + integer, intent(in)
    - + integer(kind=int64), intent(in)
    - + logical, intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=:), public,
    - + type(string_t), intent(in)
    - + type(string_t), intent(in)
    - + type(string_t), intent(in)
    - + character(len=*), intent(in)
    - + type(string_t), intent(in)
    - + type(string_t), intent(in)
    - + logical, intent(in)
    - + type(string_t), intent(in)
    - + character(len=*), intent(in),
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=:), intent(inout),
    - + type(string_t), intent(inout)
    - + character(len=*), intent(in)
    - + type(build_target_t), public,
    - + character(len=:), public,
    - + type(srcfile_t), public,
    - + character(len=:), public,
    - + type(build_target_t), intent(in),
    - + type(build_target_ptr), intent(inout),
    - + character(len=*), intent(in)
    - + type(srcfile_t), intent(in),
    - + type(preprocess_config_t), intent(in),
    - + character(len=*), intent(in),
    - + type(build_target_ptr), intent(in)
    - + type(string_t), intent(out),
    - + type(build_target_ptr), intent(in)
    - + type(string_t), intent(out),
    - + type(build_target_ptr), intent(in)
    - + type(string_t), intent(out),
    - + type(build_target_ptr), intent(inout),
    - + type(string_t), intent(in)
    - + type(error_t), intent(out),
    - + type(build_target_ptr), intent(out),
    - + type(fpm_model_t), intent(inout),
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + type(toml_table), intent(out),
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + logical, intent(inout)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + integer, intent(inout)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + integer(kind=int64), intent(inout)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + character(len=*), intent(in),
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + type(string_t), intent(in)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + logical, intent(in)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + integer, intent(in)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + integer(kind=int64), intent(in)
    - + type(error_t), intent(out),
    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit
    procedure(to_toml), public, deferred :: - dump_to_toml ../../

    Dump to TOML table, unit, file

    generic, public :: - load => load_from_toml, load_from_file, load_from_unit
    procedure(from_toml), public, deferred :: - load_from_toml ../../

    Load from TOML table, unit, file

    generic, public :: - operator(==) => serializable_is_same
    procedure(is_equal), public, deferred :: - serializable_is_same ../../

    Serializable entities need a way to check that they’re equal

    - + type(toml_table), intent(inout)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + type(string_t), intent(out),
    - + type(error_t), intent(out),
    - + type(toml_table), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + type(toml_table), intent(inout)
    - + type(string_t), intent(in),
    - + type(error_t), intent(out),
    - + type(version_t), intent(out)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + type(version_t), intent(out)
    - + integer, intent(in)
    generic, public :: - operator(==) => equals
    procedure, public :: - s ../../

    Create a printable string from a version data type

    - + type(error_t), intent(out),
    - + type(build_target_t), intent(in),
    - + type(srcfile_t), intent(inout),
    - + integer, intent(in)
    - + type(error_t), intent(out),
    - + type(srcfile_t), intent(inout),
    - + integer, intent(in)
    - + logical, intent(in),
    - + type(error_t), intent(out),
    - + type(build_target_ptr), intent(inout),
    - + character(len=*), intent(in)
    - + type(srcfile_t), intent(in),
    - + type(preprocess_config_t), intent(in),
    - + character(len=*), intent(in),
    - + class(archiver_t), intent(in)
    - + class(serializable_t), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + type(fpm_model_t), intent(out)
    - + class(fpm_build_settings), intent(inout)
    - + type(package_config_t), intent(inout)
    - + type(error_t), intent(out),
    - + type(fpm_model_t), intent(in)
    - + logical, intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + class(dependency_node_t), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + integer, public
    - + type(toml_table), intent(inout)
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + type(fpm_model_t), intent(in)
    - + class(git_target_t), intent(in)
    - + type(error_t), intent(out),
    - + character(len=:), public,
    - + integer, public
    - + type(fpm_build_settings), intent(inout)
    - + class(fpm_clean_settings), intent(in)
    - + type(fpm_export_settings), intent(inout)
    - + type(fpm_install_settings), intent(inout)
    - + type(fpm_new_settings), intent(in)
    - + type(fpm_publish_settings), intent(inout)
    - + class(fpm_run_settings), intent(inout)
    - + logical, intent(in)
    - + type(fpm_update_settings), intent(in)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + class(compiler_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + integer, public
    - + class(compiler_t), intent(in)
    - + class(serializable_t), intent(in)
    - + class(compiler_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + class(compiler_t), intent(in)
    - + character(len=:), intent(inout),
    - + type(error_t), intent(out),
    - + type(archiver_t), intent(in)
    - + type(compiler_t), intent(in)
    - + type(example_config_t), intent(out)
    - + character(len=*), intent(in)
    - + type(executable_config_t), intent(out)
    - + character(len=*), intent(in)
    - + type(library_config_t), intent(out)
    - + type(test_config_t), intent(out)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + character(len=*), intent(in)
    - + class(dependency_config_t), intent(inout)
    - + class(dependency_node_t), intent(inout)
    - + character(len=*), intent(in)
    - + class(git_target_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + integer, public
    - + class(archiver_t), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + class(compiler_t), intent(in)
    - + character(len=*), intent(in)
    - + type(string_t), intent(in)
    - + character(len=*), intent(in)
    - + character(len=:), intent(out),
    - + type(error_t), intent(out),
    - + logical, intent(in),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + type(error_t), intent(out),
    - + type(error_t), intent(out),
    - + character(len=*), intent(in)
    - + class(file_scope_flag), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + class(file_scope_flag), intent(inout)
    - + type(toml_table), intent(inout)
    - + type(error_t), intent(out),
    - + class(file_scope_flag), intent(in)
    - + class(serializable_t), intent(in)
    - + integer, intent(in)
    - + character(len=*), intent(in)
    - + integer, intent(out)
    - + character(len=*), intent(in)
    - + type(build_target_ptr), intent(in)
    - + type(string_t), intent(out),
    - + type(build_target_ptr), intent(in)
    - + type(string_t), intent(out),
    - + type(build_target_ptr), intent(in)
    - + type(string_t), intent(out),
    - + type(profile_config_t), intent(in),
    - + character(len=:), intent(in),
    - + character(len=:), intent(in),
    - + integer, public
    - + integer, intent(in)
    - + character(len=*), intent(in)
    + + + + + + + + + + + + + + + + + + +
    TypeIntentOptional AttributesName
    + + integer, + intent(in) + + ::flag + +
    + +

    Return Value + + + character(len=:), allocatable + +

    + +
    + + + + + + + + + + + +
    +

    Source Code

    +
    function FPM_UNIT_NAME(flag) result(name)
    +    integer, intent(in) :: flag
    +    character(len=:), allocatable :: name
    +
    +    select case (flag)
    +       case (FPM_UNIT_UNKNOWN);    name = "FPM_UNIT_UNKNOWN"
    +       case (FPM_UNIT_PROGRAM);    name = "FPM_UNIT_PROGRAM"
    +       case (FPM_UNIT_MODULE);     name = "FPM_UNIT_MODULE"
    +       case (FPM_UNIT_SUBMODULE);  name = "FPM_UNIT_SUBMODULE"
    +       case (FPM_UNIT_SUBPROGRAM); name = "FPM_UNIT_SUBPROGRAM"
    +       case (FPM_UNIT_CSOURCE);    name = "FPM_UNIT_CSOURCE"
    +       case (FPM_UNIT_CPPSOURCE);  name = "FPM_UNIT_CPPSOURCE"
    +       case (FPM_UNIT_CHEADER);    name = "FPM_UNIT_CHEADER"
    +       case default;               name = "INVALID"
    +    end select
    +end function FPM_UNIT_NAME
    +
    + +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/proc/fpm_version.html b/proc/fpm_version.html index 63076834f8..df88de57f5 100644 --- a/proc/fpm_version.html +++ b/proc/fpm_version.html @@ -226,7 +226,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_absolute_path.html b/proc/get_absolute_path.html index e4cf0f2a49..dfdc23480f 100644 --- a/proc/get_absolute_path.html +++ b/proc/get_absolute_path.html @@ -157,7 +157,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -187,7 +187,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -234,7 +234,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_absolute_path_by_cd.html b/proc/get_absolute_path_by_cd.html index dbced4f433..971674e281 100644 --- a/proc/get_absolute_path_by_cd.html +++ b/proc/get_absolute_path_by_cd.html @@ -157,7 +157,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -187,7 +187,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -234,7 +234,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_command_arguments_quoted.html b/proc/get_command_arguments_quoted.html index 58cac37060..9a0b0e3fc6 100644 --- a/proc/get_command_arguments_quoted.html +++ b/proc/get_command_arguments_quoted.html @@ -153,7 +153,7 @@

    Arguments


    Return Value - + character(len=:), allocatable

    @@ -229,7 +229,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_command_line_settings.html b/proc/get_command_line_settings.html index 8b32d3bf47..4cc8da3d1d 100644 --- a/proc/get_command_line_settings.html +++ b/proc/get_command_line_settings.html @@ -792,7 +792,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_compiler_id.html b/proc/get_compiler_id.html index 681322ee97..d15c40c2c8 100644 --- a/proc/get_compiler_id.html +++ b/proc/get_compiler_id.html @@ -117,12 +117,12 @@

    Variables

    @@ -177,7 +177,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -217,7 +217,7 @@

    Variables

    - + character(len=:), public, @@ -268,7 +268,7 @@

    Variables

    - + integer, public @@ -285,7 +285,7 @@

    Variables

    - + character(len=:), public, @@ -302,7 +302,7 @@

    Variables

    - + integer, public @@ -390,7 +390,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_current_directory.html b/proc/get_current_directory.html index b088fa02af..6c273ca54b 100644 --- a/proc/get_current_directory.html +++ b/proc/get_current_directory.html @@ -161,7 +161,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -176,7 +176,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -246,7 +246,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_debug_compile_flags.html b/proc/get_debug_compile_flags.html index 6bbd705ab9..dd68c2a25b 100644 --- a/proc/get_debug_compile_flags.html +++ b/proc/get_debug_compile_flags.html @@ -176,7 +176,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -323,7 +323,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_default_c_compiler.html b/proc/get_default_c_compiler.html index c98f17d394..fe64b73867 100644 --- a/proc/get_default_c_compiler.html +++ b/proc/get_default_c_compiler.html @@ -187,7 +187,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -307,7 +307,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_default_cxx_compiler.html b/proc/get_default_cxx_compiler.html index 0c4df2f013..e5b66b6fb6 100644 --- a/proc/get_default_cxx_compiler.html +++ b/proc/get_default_cxx_compiler.html @@ -188,7 +188,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -308,7 +308,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_default_flags.html b/proc/get_default_flags.html index 6ffe28ef99..a422b1baa9 100644 --- a/proc/get_default_flags.html +++ b/proc/get_default_flags.html @@ -163,7 +163,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -196,7 +196,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -250,7 +250,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_default_profiles.html b/proc/get_default_profiles.html index c34ea9abf0..c6c9bf2554 100644 --- a/proc/get_default_profiles.html +++ b/proc/get_default_profiles.html @@ -162,7 +162,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -340,7 +340,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_dos_path.html b/proc/get_dos_path.html index b06e21d130..3639dc63ea 100644 --- a/proc/get_dos_path.html +++ b/proc/get_dos_path.html @@ -165,7 +165,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -180,7 +180,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -301,7 +301,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_env.html b/proc/get_env.html index 7b5469fcbe..e430c33443 100644 --- a/proc/get_env.html +++ b/proc/get_env.html @@ -274,7 +274,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_exe_name_with_suffix.html b/proc/get_exe_name_with_suffix.html index 92a9eabf8c..a4a5c1eb09 100644 --- a/proc/get_exe_name_with_suffix.html +++ b/proc/get_exe_name_with_suffix.html @@ -162,7 +162,7 @@

    Arguments

    - + type(srcfile_t), intent(in) @@ -237,7 +237,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_feature_flag.html b/proc/get_feature_flag.html index c8b7819334..5a8c8b504d 100644 --- a/proc/get_feature_flag.html +++ b/proc/get_feature_flag.html @@ -163,7 +163,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -196,7 +196,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -338,7 +338,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_flags.html b/proc/get_flags.html index 8888ba380b..7929daa6ac 100644 --- a/proc/get_flags.html +++ b/proc/get_flags.html @@ -125,13 +125,13 @@

    Variables

    file_name file_scope_flags files - flags + flags ifile - ikey + ikey is_valid key_name link_time_flags - stat + stat @@ -188,7 +188,7 @@

    Arguments

    - + character(len=:), intent(in), @@ -248,7 +248,7 @@

    Arguments

    - + type(toml_table), intent(in), @@ -263,7 +263,7 @@

    Arguments

    - + type(profile_config_t), intent(inout), @@ -462,7 +462,7 @@

    Variables

    - + character(len=:), public, @@ -496,7 +496,7 @@

    Variables

    - + integer, public @@ -564,7 +564,7 @@

    Variables

    - + integer, public @@ -674,7 +674,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_fpm_env.html b/proc/get_fpm_env.html index 79dfdbc7e5..daeec3fc04 100644 --- a/proc/get_fpm_env.html +++ b/proc/get_fpm_env.html @@ -196,7 +196,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -247,7 +247,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_global_settings.html b/proc/get_global_settings.html index db6761bec5..96e78fa095 100644 --- a/proc/get_global_settings.html +++ b/proc/get_global_settings.html @@ -171,7 +171,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -218,7 +218,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_home.html b/proc/get_home.html index da45c58de6..aa143fe7ec 100644 --- a/proc/get_home.html +++ b/proc/get_home.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -177,7 +177,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -248,7 +248,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_id.html b/proc/get_id.html index d3420cd2ce..991918c65a 100644 --- a/proc/get_id.html +++ b/proc/get_id.html @@ -161,7 +161,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -317,7 +317,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_include_flag.html b/proc/get_include_flag.html index a63c72db48..e5c87fbb0f 100644 --- a/proc/get_include_flag.html +++ b/proc/get_include_flag.html @@ -163,7 +163,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -178,7 +178,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -196,7 +196,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -259,7 +259,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_list.html b/proc/get_list.html index 54d8dd02b7..aaa18d181d 100644 --- a/proc/get_list.html +++ b/proc/get_list.html @@ -161,7 +161,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -191,7 +191,7 @@

    Arguments

    - + type(string_t), intent(out), @@ -206,7 +206,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -305,7 +305,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_local_prefix.html b/proc/get_local_prefix.html index aab5733338..55b0ce918f 100644 --- a/proc/get_local_prefix.html +++ b/proc/get_local_prefix.html @@ -162,7 +162,7 @@

    Arguments

    - + integer, intent(in), @@ -180,7 +180,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -252,7 +252,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_macros.html b/proc/get_macros.html index 32723d8c13..4b7d0d6879 100644 --- a/proc/get_macros.html +++ b/proc/get_macros.html @@ -117,7 +117,7 @@

    Variables

    @@ -213,7 +213,7 @@

    Arguments

    - + character(len=:), intent(in), @@ -253,7 +253,7 @@

    Variables

    - + integer, public @@ -399,7 +399,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_main_flags.html b/proc/get_main_flags.html index 02ad59d4c7..a2d437f3c8 100644 --- a/proc/get_main_flags.html +++ b/proc/get_main_flags.html @@ -164,7 +164,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -179,7 +179,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -194,7 +194,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -288,7 +288,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_module_flag.html b/proc/get_module_flag.html index ddb507a0bb..a48633fc31 100644 --- a/proc/get_module_flag.html +++ b/proc/get_module_flag.html @@ -163,7 +163,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -178,7 +178,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -196,7 +196,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -275,7 +275,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_os_type.html b/proc/get_os_type.html index 65adf38abe..c0a57cc7a1 100644 --- a/proc/get_os_type.html +++ b/proc/get_os_type.html @@ -161,7 +161,7 @@

    Arguments


    Return Value - + integer

    @@ -319,7 +319,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_package_data.html b/proc/get_package_data.html index ce36e56cf6..e12a917365 100644 --- a/proc/get_package_data.html +++ b/proc/get_package_data.html @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -298,7 +298,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_registry_settings.html b/proc/get_registry_settings.html index 7fa85aa754..f53b7419a3 100644 --- a/proc/get_registry_settings.html +++ b/proc/get_registry_settings.html @@ -156,7 +156,7 @@

    Arguments

    - + type(toml_table), intent(inout), @@ -186,7 +186,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -233,7 +233,7 @@

    Arguments

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_release_compile_flags.html b/proc/get_release_compile_flags.html index 0d27841249..05a42b8977 100644 --- a/proc/get_release_compile_flags.html +++ b/proc/get_release_compile_flags.html @@ -176,7 +176,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -328,7 +328,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_temp_filename.html b/proc/get_temp_filename.html index fb9e1a6180..cfdd8ba38d 100644 --- a/proc/get_temp_filename.html +++ b/proc/get_temp_filename.html @@ -245,7 +245,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/get_working_dir.html b/proc/get_working_dir.html index ef5d01e9c8..528bf17ad7 100644 --- a/proc/get_working_dir.html +++ b/proc/get_working_dir.html @@ -162,7 +162,7 @@

    Arguments

    - + class(fpm_cmd_settings), intent(in), @@ -237,7 +237,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/getline.html b/proc/getline.html index c9339e649b..9b6b3ccdcc 100644 --- a/proc/getline.html +++ b/proc/getline.html @@ -223,7 +223,7 @@

    Arguments

    - + integer, intent(in) @@ -238,7 +238,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -253,7 +253,7 @@

    Arguments

    - + integer, intent(out) @@ -268,7 +268,7 @@

    Arguments

    - + character(len=:), @@ -361,7 +361,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/git_archive.html b/proc/git_archive.html index 0b4618a2d6..535673aa19 100644 --- a/proc/git_archive.html +++ b/proc/git_archive.html @@ -120,8 +120,8 @@

    Variables

    add_files archive_format cmd_output - i - stat + i + stat @@ -171,7 +171,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -186,7 +186,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -231,7 +231,7 @@

    Arguments

    - + logical, intent(in) @@ -246,7 +246,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -330,7 +330,7 @@

    Variables

    - + integer, public @@ -347,7 +347,7 @@

    Variables

    - + integer, public @@ -395,7 +395,7 @@

    Variables

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/git_is_same.html b/proc/git_is_same.html index b8540e8688..61031737d4 100644 --- a/proc/git_is_same.html +++ b/proc/git_is_same.html @@ -165,7 +165,7 @@

    Arguments

    - + class(git_target_t), intent(in) @@ -180,7 +180,7 @@

    Arguments

    - + class(serializable_t), intent(in) @@ -262,7 +262,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/git_matches_manifest.html b/proc/git_matches_manifest.html index 14d233cf35..5238ed6ac6 100644 --- a/proc/git_matches_manifest.html +++ b/proc/git_matches_manifest.html @@ -166,7 +166,7 @@

    Arguments

    - + type(git_target_t), intent(in) @@ -211,7 +211,7 @@

    Arguments

    - + integer, intent(in) @@ -296,7 +296,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/git_revision.html b/proc/git_revision.html index b4864bed46..82ba11111e 100644 --- a/proc/git_revision.html +++ b/proc/git_revision.html @@ -120,11 +120,11 @@

    Variables

    hexdigits iend iomsg - istart - line - stat + istart + line + stat temp_file - unit + unit workdir @@ -195,7 +195,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -210,7 +210,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -294,7 +294,7 @@

    Variables

    - + integer, public @@ -311,7 +311,7 @@

    Variables

    - + character(len=:), public, @@ -328,7 +328,7 @@

    Variables

    - + integer, public @@ -362,7 +362,7 @@

    Variables

    - + integer, public @@ -475,7 +475,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/git_target_branch.html b/proc/git_target_branch.html index 0e04395afc..e86679ed9d 100644 --- a/proc/git_target_branch.html +++ b/proc/git_target_branch.html @@ -195,7 +195,7 @@

    Arguments

    Return Value - + type(git_target_t)

    @@ -253,7 +253,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/git_target_default.html b/proc/git_target_default.html index bcea8cf61d..985a74d4c8 100644 --- a/proc/git_target_default.html +++ b/proc/git_target_default.html @@ -180,7 +180,7 @@

    Arguments

    Return Value - + type(git_target_t)

    @@ -234,7 +234,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/git_target_revision.html b/proc/git_target_revision.html index 2538405778..1bf29ae6b7 100644 --- a/proc/git_target_revision.html +++ b/proc/git_target_revision.html @@ -195,7 +195,7 @@

    Arguments

    Return Value - + type(git_target_t)

    @@ -253,7 +253,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/git_target_tag.html b/proc/git_target_tag.html index c08b842863..217cd0e6bd 100644 --- a/proc/git_target_tag.html +++ b/proc/git_target_tag.html @@ -195,7 +195,7 @@

    Arguments

    Return Value - + type(git_target_t)

    @@ -253,7 +253,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/glob.html b/proc/glob.html index 23b6ab8881..a086e88861 100644 --- a/proc/glob.html +++ b/proc/glob.html @@ -554,7 +554,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/handle_error~2.html b/proc/handle_error.html similarity index 98% rename from proc/handle_error~2.html rename to proc/handle_error.html index 5040a24a51..d9890b7150 100644 --- a/proc/handle_error~2.html +++ b/proc/handle_error.html @@ -132,7 +132,7 @@

    Contents

    Source Code

    @@ -221,7 +221,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/has_manifest.html b/proc/has_manifest.html index 276be889de..b1c9fad575 100644 --- a/proc/has_manifest.html +++ b/proc/has_manifest.html @@ -161,7 +161,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -227,7 +227,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/has_valid_custom_prefix.html b/proc/has_valid_custom_prefix.html index 44e1e958d5..2db7b350a4 100644 --- a/proc/has_valid_custom_prefix.html +++ b/proc/has_valid_custom_prefix.html @@ -171,7 +171,7 @@

    Arguments

    - + type(string_t), intent(in) @@ -288,7 +288,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/has_valid_standard_prefix.html b/proc/has_valid_standard_prefix.html index 87e532e232..10367aa1f0 100644 --- a/proc/has_valid_standard_prefix.html +++ b/proc/has_valid_standard_prefix.html @@ -171,7 +171,7 @@

    Arguments

    - + type(string_t), intent(in) @@ -186,7 +186,7 @@

    Arguments

    - + type(string_t), intent(in) @@ -292,7 +292,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/info_profile.html b/proc/info_profile.html index d9b441e322..fc1097c6c0 100644 --- a/proc/info_profile.html +++ b/proc/info_profile.html @@ -117,7 +117,7 @@

    Variables

    - i + i
    @@ -191,7 +191,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -213,7 +213,7 @@

    Variables

    - + integer, public @@ -316,7 +316,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/info~3.html b/proc/info~4.html similarity index 97% rename from proc/info~3.html rename to proc/info~4.html index 0c3e14f96e..4b86c6d4a7 100644 --- a/proc/info~3.html +++ b/proc/info~4.html @@ -117,8 +117,8 @@

    Variables

    - fmt - pr + fmt + pr
    @@ -144,7 +144,7 @@

    Variables

    Source Code

    - info + info
    @@ -176,7 +176,7 @@

    Arguments

    - + class(git_target_t), intent(in) @@ -191,7 +191,7 @@

    Arguments

    - + integer, intent(in) @@ -239,7 +239,7 @@

    Variables

    - + character(len=*), public, @@ -256,7 +256,7 @@

    Variables

    - + integer, public @@ -350,7 +350,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/info~2.html b/proc/info~6.html similarity index 96% rename from proc/info~2.html rename to proc/info~6.html index c79898f88c..401591e494 100644 --- a/proc/info~2.html +++ b/proc/info~6.html @@ -117,8 +117,8 @@

    Variables

    - fmt - pr + fmt + pr
    @@ -144,7 +144,7 @@

    Variables

    Source Code

    - info + info
    @@ -176,7 +176,7 @@

    Arguments

    - + class(profile_config_t), intent(in) @@ -191,7 +191,7 @@

    Arguments

    - + integer, intent(in) @@ -206,7 +206,7 @@

    Arguments

    - + integer, intent(in), @@ -239,7 +239,7 @@

    Variables

    - + character(len=*), public, @@ -256,7 +256,7 @@

    Variables

    - + integer, public @@ -346,7 +346,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_absolute_path.html b/proc/is_absolute_path.html index 788bba40cc..e938c1160a 100644 --- a/proc/is_absolute_path.html +++ b/proc/is_absolute_path.html @@ -163,7 +163,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -178,7 +178,7 @@

    Arguments

    - + logical, intent(in), @@ -262,7 +262,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_dir.html b/proc/is_dir.html index 545ca68be6..6b150c88ac 100644 --- a/proc/is_dir.html +++ b/proc/is_dir.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -241,7 +241,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_fortran_name.html b/proc/is_fortran_name.html index 7d6c5fbb0a..22415c3fd5 100644 --- a/proc/is_fortran_name.html +++ b/proc/is_fortran_name.html @@ -161,7 +161,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -241,7 +241,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_gnu.html b/proc/is_gnu.html index e854e66181..8f098a052a 100644 --- a/proc/is_gnu.html +++ b/proc/is_gnu.html @@ -163,7 +163,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -227,7 +227,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_hidden_file.html b/proc/is_hidden_file.html index 1c39346bdd..5a780fefb9 100644 --- a/proc/is_hidden_file.html +++ b/proc/is_hidden_file.html @@ -180,7 +180,7 @@

    Arguments

    Return Value - + logical

    @@ -230,7 +230,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_intel.html b/proc/is_intel.html index 4addaeb727..7593f8c524 100644 --- a/proc/is_intel.html +++ b/proc/is_intel.html @@ -163,7 +163,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -228,7 +228,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_meta_package.html b/proc/is_meta_package.html index 12ad23dbce..47b82ae2cf 100644 --- a/proc/is_meta_package.html +++ b/proc/is_meta_package.html @@ -240,7 +240,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_unknown.html b/proc/is_unknown.html index 72f263ee40..885611924a 100644 --- a/proc/is_unknown.html +++ b/proc/is_unknown.html @@ -163,7 +163,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -228,7 +228,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_valid_module_name.html b/proc/is_valid_module_name.html index 0baa1ad860..6bc4d0f21d 100644 --- a/proc/is_valid_module_name.html +++ b/proc/is_valid_module_name.html @@ -167,7 +167,7 @@

    Arguments

    - + type(string_t), intent(in) @@ -182,7 +182,7 @@

    Arguments

    - + type(string_t), intent(in) @@ -212,7 +212,7 @@

    Arguments

    - + logical, intent(in) @@ -297,7 +297,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/is_valid_module_prefix.html b/proc/is_valid_module_prefix.html index 3ccf2137b0..75ae47104f 100644 --- a/proc/is_valid_module_prefix.html +++ b/proc/is_valid_module_prefix.html @@ -164,7 +164,7 @@

    Arguments

    - + type(string_t), intent(in) @@ -246,7 +246,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/join.html b/proc/join.html index 1ef2482d00..780271ef14 100644 --- a/proc/join.html +++ b/proc/join.html @@ -253,7 +253,7 @@

    Arguments

    - + character(len=*), intent(in), @@ -346,7 +346,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -423,7 +423,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/join_path.html b/proc/join_path.html index c7e8d57e37..2e9a7ed5c9 100644 --- a/proc/join_path.html +++ b/proc/join_path.html @@ -240,7 +240,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -331,7 +331,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/link.html b/proc/link.html index c5ab7dc0ef..66043b0160 100644 --- a/proc/link.html +++ b/proc/link.html @@ -164,7 +164,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -179,7 +179,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -224,7 +224,7 @@

    Arguments

    - + integer, intent(out) @@ -292,7 +292,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/list_files.html b/proc/list_files.html index 2d1a8d1308..840e53f619 100644 --- a/proc/list_files.html +++ b/proc/list_files.html @@ -166,7 +166,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -181,7 +181,7 @@

    Arguments

    - + type(string_t), intent(out), @@ -196,7 +196,7 @@

    Arguments

    - + logical, intent(in), @@ -329,7 +329,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/load_from_toml~3.html b/proc/load_from_toml~4.html similarity index 97% rename from proc/load_from_toml~3.html rename to proc/load_from_toml~4.html index 4cb4f68ab1..a72b396fd0 100644 --- a/proc/load_from_toml~3.html +++ b/proc/load_from_toml~4.html @@ -117,7 +117,7 @@

    Variables

    @@ -143,7 +143,7 @@

    Variables

    Source Code

    @@ -177,7 +177,7 @@

    Arguments

    - + class(git_target_t), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -207,7 +207,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -323,7 +323,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/load_from_toml~8.html b/proc/load_from_toml~9.html similarity index 98% rename from proc/load_from_toml~8.html rename to proc/load_from_toml~9.html index 6b5b5b0d2b..72838cecf6 100644 --- a/proc/load_from_toml~8.html +++ b/proc/load_from_toml~9.html @@ -132,7 +132,7 @@

    Contents

    Source Code

    @@ -164,7 +164,7 @@

    Arguments

    - + class(archiver_t), intent(inout) @@ -179,7 +179,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -194,7 +194,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -268,7 +268,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/lower.html b/proc/lower.html index e221781a7b..eac499e57c 100644 --- a/proc/lower.html +++ b/proc/lower.html @@ -212,7 +212,7 @@

    Arguments

    Return Value - + character(len=len(str))

    @@ -282,7 +282,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/make_archive.html b/proc/make_archive.html index 3343219639..3593f24820 100644 --- a/proc/make_archive.html +++ b/proc/make_archive.html @@ -181,7 +181,7 @@

    Arguments

    - + class(archiver_t), intent(in) @@ -196,7 +196,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -241,7 +241,7 @@

    Arguments

    - + integer, intent(out) @@ -289,7 +289,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -372,7 +372,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/manifest_has_changed.html b/proc/manifest_has_changed.html index 7432229e11..5cc7236241 100644 --- a/proc/manifest_has_changed.html +++ b/proc/manifest_has_changed.html @@ -164,7 +164,7 @@

    Arguments

    - + class(dependency_config_t), intent(in) @@ -179,7 +179,7 @@

    Arguments

    - + class(dependency_config_t), intent(in) @@ -194,7 +194,7 @@

    Arguments

    - + integer, intent(in) @@ -209,7 +209,7 @@

    Arguments

    - + integer, intent(in) @@ -292,7 +292,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/match_os_type.html b/proc/match_os_type.html index 8071f147b6..a49388f5aa 100644 --- a/proc/match_os_type.html +++ b/proc/match_os_type.html @@ -251,7 +251,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/mkdir.html b/proc/mkdir.html index b1711bf2de..d9192df7b3 100644 --- a/proc/mkdir.html +++ b/proc/mkdir.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -177,7 +177,7 @@

    Arguments

    - + logical, intent(in), @@ -252,7 +252,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/module_prefix_template.html b/proc/module_prefix_template.html index 998be14c5b..cd282f5619 100644 --- a/proc/module_prefix_template.html +++ b/proc/module_prefix_template.html @@ -194,7 +194,7 @@

    Arguments

    Return Value - + type(string_t)

    @@ -251,7 +251,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/module_prefix_type.html b/proc/module_prefix_type.html index f4420a3d7a..f5b161069a 100644 --- a/proc/module_prefix_type.html +++ b/proc/module_prefix_type.html @@ -247,7 +247,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/mpi_type_name.html b/proc/mpi_type_name.html index a6eacfc406..1f15d3f705 100644 --- a/proc/mpi_type_name.html +++ b/proc/mpi_type_name.html @@ -180,7 +180,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -234,7 +234,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/name_is_json.html b/proc/name_is_json.html index 18f26c0746..afdcfc3080 100644 --- a/proc/name_is_json.html +++ b/proc/name_is_json.html @@ -234,7 +234,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_archiver.html b/proc/new_archiver.html index 0b0fca485f..56789c3792 100644 --- a/proc/new_archiver.html +++ b/proc/new_archiver.html @@ -120,7 +120,7 @@

    Variables

    arflags estat libflags - os_type + os_type @@ -176,7 +176,7 @@

    Arguments

    - + type(archiver_t), intent(out) @@ -206,7 +206,7 @@

    Arguments

    - + logical, intent(in) @@ -221,7 +221,7 @@

    Arguments

    - + logical, intent(in) @@ -305,7 +305,7 @@

    Variables

    - + integer, public @@ -417,7 +417,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_build_config.html b/proc/new_build_config.html index 31ad8efd16..2b07b604a3 100644 --- a/proc/new_build_config.html +++ b/proc/new_build_config.html @@ -164,7 +164,7 @@

    Arguments

    - + type(build_config_t), intent(out) @@ -179,7 +179,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -194,7 +194,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -209,7 +209,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -338,7 +338,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_compiler.html b/proc/new_compiler.html index cc6ae890be..3e8995f07d 100644 --- a/proc/new_compiler.html +++ b/proc/new_compiler.html @@ -162,7 +162,7 @@

    Arguments

    - + type(compiler_t), intent(out) @@ -222,7 +222,7 @@

    Arguments

    - + logical, intent(in) @@ -237,7 +237,7 @@

    Arguments

    - + logical, intent(in) @@ -322,7 +322,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_dependencies.html b/proc/new_dependencies.html index 1db2223854..ba1cd7e6b4 100644 --- a/proc/new_dependencies.html +++ b/proc/new_dependencies.html @@ -181,7 +181,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -196,7 +196,7 @@

    Arguments

    - + character(len=*), intent(in), @@ -211,7 +211,7 @@

    Arguments

    - + type(metapackage_config_t), intent(out), @@ -226,7 +226,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -360,7 +360,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_dependency.html b/proc/new_dependency.html index 3a309907c3..89b1289e56 100644 --- a/proc/new_dependency.html +++ b/proc/new_dependency.html @@ -163,7 +163,7 @@

    Arguments

    - + type(dependency_config_t), intent(out) @@ -178,7 +178,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -193,7 +193,7 @@

    Arguments

    - + character(len=*), intent(in), @@ -208,7 +208,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -335,7 +335,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_dependency_node.html b/proc/new_dependency_node.html index a0f2a99b8b..73bc4afb30 100644 --- a/proc/new_dependency_node.html +++ b/proc/new_dependency_node.html @@ -162,7 +162,7 @@

    Arguments

    - + type(dependency_node_t), intent(out) @@ -302,7 +302,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_dependency_tree.html b/proc/new_dependency_tree.html index 35076eabdc..b7c79d6419 100644 --- a/proc/new_dependency_tree.html +++ b/proc/new_dependency_tree.html @@ -162,7 +162,7 @@

    Arguments

    - + type(dependency_tree_t), intent(out) @@ -177,7 +177,7 @@

    Arguments

    - + integer, intent(in), @@ -261,7 +261,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_example.html b/proc/new_example.html index 4717ca0ebe..2a71b093dc 100644 --- a/proc/new_example.html +++ b/proc/new_example.html @@ -162,7 +162,7 @@

    Arguments

    - + type(example_config_t), intent(out) @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -282,7 +282,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_executable.html b/proc/new_executable.html index e882d1eaf3..3bf9375b70 100644 --- a/proc/new_executable.html +++ b/proc/new_executable.html @@ -162,7 +162,7 @@

    Arguments

    - + type(executable_config_t), intent(out) @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -282,7 +282,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_fortran_config.html b/proc/new_fortran_config.html index 58dd177575..f4c17ecf71 100644 --- a/proc/new_fortran_config.html +++ b/proc/new_fortran_config.html @@ -162,7 +162,7 @@

    Arguments

    - + type(fortran_config_t), intent(out) @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -291,7 +291,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_install_config.html b/proc/new_install_config.html index d17aa781a0..b9f4a3db3a 100644 --- a/proc/new_install_config.html +++ b/proc/new_install_config.html @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -262,7 +262,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_installer.html b/proc/new_installer.html index e94b47682e..9383c2eddb 100644 --- a/proc/new_installer.html +++ b/proc/new_installer.html @@ -162,7 +162,7 @@

    Arguments

    - + type(installer_t), intent(out) @@ -237,7 +237,7 @@

    Arguments

    - + integer, intent(in), @@ -252,7 +252,7 @@

    Arguments

    - + character(len=*), intent(in), @@ -393,7 +393,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_library.html b/proc/new_library.html index 557f954751..8fc5e29462 100644 --- a/proc/new_library.html +++ b/proc/new_library.html @@ -162,7 +162,7 @@

    Arguments

    - + type(library_config_t), intent(out) @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -271,7 +271,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_meta_config.html b/proc/new_meta_config.html index a5ab3bc153..9f108d905b 100644 --- a/proc/new_meta_config.html +++ b/proc/new_meta_config.html @@ -164,7 +164,7 @@

    Arguments

    - + type(metapackage_config_t), intent(out) @@ -179,7 +179,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -209,7 +209,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -296,7 +296,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_meta_request.html b/proc/new_meta_request.html index 15d9c7654b..f4120071e5 100644 --- a/proc/new_meta_request.html +++ b/proc/new_meta_request.html @@ -166,7 +166,7 @@

    Arguments

    - + type(metapackage_request_t), intent(out) @@ -196,7 +196,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -226,7 +226,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -348,7 +348,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_package.html b/proc/new_package.html index f2bbd99035..c10f4ff99b 100644 --- a/proc/new_package.html +++ b/proc/new_package.html @@ -162,7 +162,7 @@

    Arguments

    - + type(package_config_t), intent(out) @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + character(len=*), intent(in), @@ -207,7 +207,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -454,7 +454,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_preprocess_config.html b/proc/new_preprocess_config.html index e7f60ca4e9..b626f44cea 100644 --- a/proc/new_preprocess_config.html +++ b/proc/new_preprocess_config.html @@ -162,7 +162,7 @@

    Arguments

    - + type(preprocess_config_t), intent(out) @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -271,7 +271,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_preprocessors.html b/proc/new_preprocessors.html index c32f33b988..a970caa9de 100644 --- a/proc/new_preprocessors.html +++ b/proc/new_preprocessors.html @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -279,7 +279,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_profile.html b/proc/new_profile.html index 281f328992..6cacc9a507 100644 --- a/proc/new_profile.html +++ b/proc/new_profile.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -177,7 +177,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -207,7 +207,7 @@

    Arguments

    - + character(len=*), intent(in), @@ -408,7 +408,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_profiles.html b/proc/new_profiles.html index 885f1a0b20..1394b990bb 100644 --- a/proc/new_profiles.html +++ b/proc/new_profiles.html @@ -125,10 +125,10 @@

    Variables

    os_list prof_list prof_node - profile_name + profile_name profiles_size profindex - stat + stat @@ -184,7 +184,7 @@

    Arguments

    - + type(profile_config_t), intent(out), @@ -199,7 +199,7 @@

    Arguments

    - + type(toml_table), intent(inout), @@ -214,7 +214,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -383,7 +383,7 @@

    Variables

    - + character(len=:), public, @@ -434,7 +434,7 @@

    Variables

    - + integer, public @@ -602,7 +602,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/new_test.html b/proc/new_test.html index 58ded7db41..abf1216497 100644 --- a/proc/new_test.html +++ b/proc/new_test.html @@ -162,7 +162,7 @@

    Arguments

    - + type(test_config_t), intent(out) @@ -177,7 +177,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -282,7 +282,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/notabs.html b/proc/notabs.html index 576408a522..1f12506c31 100644 --- a/proc/notabs.html +++ b/proc/notabs.html @@ -343,7 +343,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/number_of_rows.html b/proc/number_of_rows.html index 4810670dd4..8586a2ad8f 100644 --- a/proc/number_of_rows.html +++ b/proc/number_of_rows.html @@ -162,7 +162,7 @@

    Arguments

    - + integer, intent(in) @@ -234,7 +234,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/os_delete_dir.html b/proc/os_delete_dir.html index e002cc4283..a0a6b2c513 100644 --- a/proc/os_delete_dir.html +++ b/proc/os_delete_dir.html @@ -162,7 +162,7 @@

    Arguments

    - + logical, intent(in) @@ -177,7 +177,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -192,7 +192,7 @@

    Arguments

    - + logical, intent(in), @@ -257,7 +257,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/os_is_unix.html b/proc/os_is_unix.html index 99b9819759..5e69a2d688 100644 --- a/proc/os_is_unix.html +++ b/proc/os_is_unix.html @@ -164,7 +164,7 @@

    Arguments

    - + integer, intent(in), @@ -234,7 +234,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/os_name.html b/proc/os_name.html index 936b8943d1..6816d4741f 100644 --- a/proc/os_name.html +++ b/proc/os_name.html @@ -162,7 +162,7 @@

    Arguments

    - + integer, intent(in) @@ -238,7 +238,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/os_type_name.html b/proc/os_type_name.html index cba42d7f95..77d53a29ee 100644 --- a/proc/os_type_name.html +++ b/proc/os_type_name.html @@ -236,7 +236,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/parent_dir.html b/proc/parent_dir.html index 58dcc477ea..db2b74620b 100644 --- a/proc/parent_dir.html +++ b/proc/parent_dir.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -180,7 +180,7 @@

    Arguments

    Return Value - + character(len=:), allocatable

    @@ -229,7 +229,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/parse_c_source.html b/proc/parse_c_source.html index 790445b1fc..19aa89d237 100644 --- a/proc/parse_c_source.html +++ b/proc/parse_c_source.html @@ -181,7 +181,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -313,7 +313,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/parse_descriptor.html b/proc/parse_descriptor.html index 03f909fe30..a8e975ecde 100644 --- a/proc/parse_descriptor.html +++ b/proc/parse_descriptor.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -234,7 +234,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/parse_f_source.html b/proc/parse_f_source.html index f07387e743..db9efe4050 100644 --- a/proc/parse_f_source.html +++ b/proc/parse_f_source.html @@ -201,7 +201,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -508,8 +508,10 @@

    Source Code

    end if ! Detect if contains a program - ! (no modules allowed after program def) - if (index(file_lines_lower(i)%s,'program ') == 1) then + ! - no modules allowed after program def + ! - program header may be missing (only "end program" statement present) + if (index(file_lines_lower(i)%s,'program ')==1 .or. & + parse_sequence(file_lines_lower(i)%s,'end','program')) then temp_string = split_n(file_lines_lower(i)%s,n=2,delims=' ',stat=stat) if (stat == 0) then @@ -526,6 +528,7 @@

    Source Code

    f_source%unit_type = FPM_UNIT_PROGRAM cycle + end if @@ -587,7 +590,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/parse_use_statement.html b/proc/parse_use_statement.html index d8cf9b1c33..0849f67b3f 100644 --- a/proc/parse_use_statement.html +++ b/proc/parse_use_statement.html @@ -176,7 +176,7 @@

    Arguments

    - + integer, intent(in) @@ -191,7 +191,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -236,7 +236,7 @@

    Arguments

    - + character(len=:), intent(out), @@ -251,7 +251,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -411,7 +411,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/pkgcfg_get_build_flags.html b/proc/pkgcfg_get_build_flags.html index 320b9ea076..0be88fc265 100644 --- a/proc/pkgcfg_get_build_flags.html +++ b/proc/pkgcfg_get_build_flags.html @@ -163,7 +163,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -194,7 +194,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -324,7 +324,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/pkgcfg_get_libs.html b/proc/pkgcfg_get_libs.html index 21a1228388..0cd70e27f4 100644 --- a/proc/pkgcfg_get_libs.html +++ b/proc/pkgcfg_get_libs.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -177,7 +177,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -278,7 +278,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/pkgcfg_get_version.html b/proc/pkgcfg_get_version.html index 0f8f8e8981..5933f1a486 100644 --- a/proc/pkgcfg_get_version.html +++ b/proc/pkgcfg_get_version.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -177,7 +177,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -261,7 +261,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/pkgcfg_has_package.html b/proc/pkgcfg_has_package.html index 0f0b7eea02..d99d183483 100644 --- a/proc/pkgcfg_has_package.html +++ b/proc/pkgcfg_has_package.html @@ -163,7 +163,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -240,7 +240,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/pkgcfg_list_all.html b/proc/pkgcfg_list_all.html index 36d24bc33d..d058b3e952 100644 --- a/proc/pkgcfg_list_all.html +++ b/proc/pkgcfg_list_all.html @@ -163,7 +163,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -293,7 +293,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/profile_dump.html b/proc/profile_dump.html index d2d5d0508f..265857b28a 100644 --- a/proc/profile_dump.html +++ b/proc/profile_dump.html @@ -117,11 +117,11 @@

    Variables

    @@ -180,7 +180,7 @@

    Arguments

    - + class(profile_config_t), intent(inout) @@ -195,7 +195,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -210,7 +210,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -243,7 +243,7 @@

    Variables

    - + integer, public @@ -260,7 +260,7 @@

    Variables

    - + integer, public @@ -277,7 +277,7 @@

    Variables

    - + type(toml_table), public, @@ -311,7 +311,7 @@

    Variables

    - + character(len=30), public @@ -432,7 +432,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/profile_load.html b/proc/profile_load.html index 6bcc9bc9e7..530f16b011 100644 --- a/proc/profile_load.html +++ b/proc/profile_load.html @@ -118,11 +118,11 @@

    Variables

    dep_keys - flag - ii - jj - keys - ptr + flag + ii + jj + keys + ptr ptr_dep
    @@ -182,7 +182,7 @@

    Arguments

    - + class(profile_config_t), intent(inout) @@ -197,7 +197,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -212,7 +212,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -262,7 +262,7 @@

    Variables

    - + character(len=:), public, @@ -279,7 +279,7 @@

    Variables

    - + integer, public @@ -296,7 +296,7 @@

    Variables

    - + integer, public @@ -313,7 +313,7 @@

    Variables

    - + type(toml_key), public, @@ -330,7 +330,7 @@

    Variables

    - + type(toml_table), public, @@ -459,7 +459,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/profile_same.html b/proc/profile_same.html index abe4829815..9405a1fb3a 100644 --- a/proc/profile_same.html +++ b/proc/profile_same.html @@ -117,7 +117,7 @@

    Variables

    - ii + ii
    @@ -175,7 +175,7 @@

    Arguments

    - + class(profile_config_t), intent(in) @@ -190,7 +190,7 @@

    Arguments

    - + class(serializable_t), intent(in) @@ -230,7 +230,7 @@

    Variables

    - + integer, public @@ -340,7 +340,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/read_lines.html b/proc/read_lines.html index 75718c0d49..0bb210fc66 100644 --- a/proc/read_lines.html +++ b/proc/read_lines.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -180,7 +180,7 @@

    Arguments

    Return Value - + type(string_t), allocatable, (:)

    @@ -245,7 +245,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/read_lines_expanded.html b/proc/read_lines_expanded.html index 796c992cc8..636af65af8 100644 --- a/proc/read_lines_expanded.html +++ b/proc/read_lines_expanded.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -180,7 +180,7 @@

    Arguments

    Return Value - + type(string_t), allocatable, (:)

    @@ -245,7 +245,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/read_package_file.html b/proc/read_package_file.html index c1865d90ce..e2cb739353 100644 --- a/proc/read_package_file.html +++ b/proc/read_package_file.html @@ -162,7 +162,7 @@

    Arguments

    - + type(toml_table), intent(out), @@ -177,7 +177,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -192,7 +192,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -278,7 +278,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/regex_version_from_text.html b/proc/regex_version_from_text.html index 4b60186da2..caaf6f5a45 100644 --- a/proc/regex_version_from_text.html +++ b/proc/regex_version_from_text.html @@ -191,7 +191,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -209,7 +209,7 @@

    Arguments

    Return Value - + type(string_t)

    @@ -282,7 +282,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/remove_characters_in_set.html b/proc/remove_characters_in_set.html index ecbb804c35..e71d815b53 100644 --- a/proc/remove_characters_in_set.html +++ b/proc/remove_characters_in_set.html @@ -161,7 +161,7 @@

    Arguments

    - + character(len=:), intent(inout), @@ -284,7 +284,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/remove_newline_characters.html b/proc/remove_newline_characters.html index fe6002b0d6..40d662cdf8 100644 --- a/proc/remove_newline_characters.html +++ b/proc/remove_newline_characters.html @@ -161,7 +161,7 @@

    Arguments

    - + type(string_t), intent(inout) @@ -225,7 +225,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/replace.html b/proc/replace.html index d7c2499579..c192d8d479 100644 --- a/proc/replace.html +++ b/proc/replace.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -264,7 +264,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/resolve_module_dependencies.html b/proc/resolve_module_dependencies.html index b9bfcc0c87..0be4ec9769 100644 --- a/proc/resolve_module_dependencies.html +++ b/proc/resolve_module_dependencies.html @@ -184,7 +184,7 @@

    Arguments

    - + type(build_target_ptr), intent(inout), @@ -199,7 +199,7 @@

    Arguments

    - + type(string_t), intent(in) @@ -214,7 +214,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -317,7 +317,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/run_wrapper.html b/proc/run_wrapper.html index 59e1242371..75b4e5e405 100644 --- a/proc/run_wrapper.html +++ b/proc/run_wrapper.html @@ -192,7 +192,7 @@

    Arguments

    - + logical, intent(in), @@ -377,7 +377,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/run~2.html b/proc/run~2.html index ec4a985bd0..b0a66ffce5 100644 --- a/proc/run~2.html +++ b/proc/run~2.html @@ -219,7 +219,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -234,7 +234,7 @@

    Arguments

    - + logical, intent(in), @@ -264,7 +264,7 @@

    Arguments

    - + logical, intent(in), @@ -410,7 +410,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/schedule_targets.html b/proc/schedule_targets.html index b384ac6f57..b5b6b4edd3 100644 --- a/proc/schedule_targets.html +++ b/proc/schedule_targets.html @@ -291,7 +291,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/separator.html b/proc/separator.html index 247cb3b3ee..88c7506ac2 100644 --- a/proc/separator.html +++ b/proc/separator.html @@ -188,7 +188,7 @@

    Arguments


    Return Value - + character(len=1)

    @@ -320,7 +320,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/set_cpp_preprocessor_flags.html b/proc/set_cpp_preprocessor_flags.html index ad1c7e907a..e190eedc71 100644 --- a/proc/set_cpp_preprocessor_flags.html +++ b/proc/set_cpp_preprocessor_flags.html @@ -188,7 +188,7 @@

    Arguments

    - + character(len=:), intent(inout), @@ -297,7 +297,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/set_env.html b/proc/set_env.html index d3a282a9a9..0db5b91cde 100644 --- a/proc/set_env.html +++ b/proc/set_env.html @@ -165,7 +165,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -180,7 +180,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -301,7 +301,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/set_list.html b/proc/set_list.html index 8bc9adcd90..a540c70b85 100644 --- a/proc/set_list.html +++ b/proc/set_list.html @@ -164,7 +164,7 @@

    Arguments

    - + type(toml_table), intent(inout) @@ -194,7 +194,7 @@

    Arguments

    - + type(string_t), intent(in), @@ -209,7 +209,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -319,7 +319,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/show_model.html b/proc/show_model.html index 5eff01f73a..e346e8bb41 100644 --- a/proc/show_model.html +++ b/proc/show_model.html @@ -161,7 +161,7 @@

    Arguments

    - + type(fpm_model_t), intent(in) @@ -219,7 +219,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/sort_target.html b/proc/sort_target.html index 3a268b00eb..0e750ceef2 100644 --- a/proc/sort_target.html +++ b/proc/sort_target.html @@ -293,7 +293,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/split.html b/proc/split.html index e4c3b6933e..0a303e8cc0 100644 --- a/proc/split.html +++ b/proc/split.html @@ -395,7 +395,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/split_first_last.html b/proc/split_first_last.html index 2fcbd38cc1..7ddd510906 100644 --- a/proc/split_first_last.html +++ b/proc/split_first_last.html @@ -161,7 +161,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -285,7 +285,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/str_begins_with_str.html b/proc/str_begins_with_str.html index 003c4fcd19..82747f9dc0 100644 --- a/proc/str_begins_with_str.html +++ b/proc/str_begins_with_str.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -275,7 +275,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/string_array_contains.html b/proc/string_array_contains.html index 7e09c31f01..5114a8f3cf 100644 --- a/proc/string_array_contains.html +++ b/proc/string_array_contains.html @@ -247,7 +247,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/string_cat.html b/proc/string_cat.html index 44830603cc..d8f34fcf4f 100644 --- a/proc/string_cat.html +++ b/proc/string_cat.html @@ -265,7 +265,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/syntax_error.html b/proc/syntax_error.html index 45c4de4550..4f174384a1 100644 --- a/proc/syntax_error.html +++ b/proc/syntax_error.html @@ -161,7 +161,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -176,7 +176,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -241,7 +241,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/targets_from_sources.html b/proc/targets_from_sources.html index e31ef48e38..ef02fb04f7 100644 --- a/proc/targets_from_sources.html +++ b/proc/targets_from_sources.html @@ -162,7 +162,7 @@

    Arguments

    - + type(build_target_ptr), intent(out), @@ -177,7 +177,7 @@

    Arguments

    - + type(fpm_model_t), intent(inout), @@ -207,7 +207,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -288,7 +288,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/to_fortran_name.html b/proc/to_fortran_name.html index b9eaaa70ae..bdf013299b 100644 --- a/proc/to_fortran_name.html +++ b/proc/to_fortran_name.html @@ -164,7 +164,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -230,7 +230,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/traverse_compilers.html b/proc/traverse_compilers.html index f2ef9dd67b..af2c802041 100644 --- a/proc/traverse_compilers.html +++ b/proc/traverse_compilers.html @@ -122,7 +122,7 @@

    Variables

    icomp is_valid os_list - stat + stat @@ -178,7 +178,7 @@

    Arguments

    - + character(len=:), intent(in), @@ -208,7 +208,7 @@

    Arguments

    - + type(toml_table), intent(in), @@ -223,7 +223,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -253,7 +253,7 @@

    Arguments

    - + type(profile_config_t), intent(inout), @@ -386,7 +386,7 @@

    Variables

    - + integer, public @@ -497,7 +497,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/traverse_oss.html b/proc/traverse_oss.html index 8d6201622c..628df484c3 100644 --- a/proc/traverse_oss.html +++ b/proc/traverse_oss.html @@ -125,7 +125,7 @@

    Variables

    os_name os_node os_type - stat + stat @@ -181,7 +181,7 @@

    Arguments

    - + character(len=:), intent(in), @@ -226,7 +226,7 @@

    Arguments

    - + type(toml_table), intent(in), @@ -241,7 +241,7 @@

    Arguments

    - + type(profile_config_t), intent(inout), @@ -271,7 +271,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -440,7 +440,7 @@

    Variables

    - + integer, public @@ -558,7 +558,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/traverse_oss_for_size.html b/proc/traverse_oss_for_size.html index eb32e2f212..0cbdce9d95 100644 --- a/proc/traverse_oss_for_size.html +++ b/proc/traverse_oss_for_size.html @@ -125,7 +125,7 @@

    Variables

    l_os_name os_name os_node - stat + stat @@ -181,7 +181,7 @@

    Arguments

    - + character(len=:), intent(in), @@ -226,7 +226,7 @@

    Arguments

    - + type(toml_table), intent(in), @@ -256,7 +256,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -425,7 +425,7 @@

    Variables

    - + integer, public @@ -547,7 +547,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/unix_path.html b/proc/unix_path.html index 02139986cb..b2fd006fb0 100644 --- a/proc/unix_path.html +++ b/proc/unix_path.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -238,7 +238,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/upper.html b/proc/upper.html index 3be6781f47..b6f7be7f2b 100644 --- a/proc/upper.html +++ b/proc/upper.html @@ -209,7 +209,7 @@

    Arguments

    Return Value - + character(len=len(str))

    @@ -279,7 +279,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/validate_compiler_name.html b/proc/validate_compiler_name.html index 89b9d0d607..8cde519e58 100644 --- a/proc/validate_compiler_name.html +++ b/proc/validate_compiler_name.html @@ -245,7 +245,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/validate_os_name.html b/proc/validate_os_name.html index 3fc69bfac2..989eafb006 100644 --- a/proc/validate_os_name.html +++ b/proc/validate_os_name.html @@ -247,7 +247,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/validate_profile_table.html b/proc/validate_profile_table.html index e501e010a4..240e03d105 100644 --- a/proc/validate_profile_table.html +++ b/proc/validate_profile_table.html @@ -124,13 +124,13 @@

    Variables

    file_list file_name files - flags + flags ifile - ikey + ikey is_valid key_name link_time_flags - stat + stat @@ -185,7 +185,7 @@

    Arguments

    - + character(len=:), intent(in), @@ -230,7 +230,7 @@

    Arguments

    - + type(toml_table), intent(in), @@ -245,7 +245,7 @@

    Arguments

    - + type(error_t), intent(out), @@ -412,7 +412,7 @@

    Variables

    - + character(len=:), public, @@ -446,7 +446,7 @@

    Variables

    - + integer, public @@ -514,7 +514,7 @@

    Variables

    - + integer, public @@ -650,7 +650,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/warnwrite.html b/proc/warnwrite.html index cf905cd3c7..cd600e9998 100644 --- a/proc/warnwrite.html +++ b/proc/warnwrite.html @@ -242,7 +242,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/which.html b/proc/which.html index df28d6a911..76cc616bfe 100644 --- a/proc/which.html +++ b/proc/which.html @@ -200,7 +200,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -297,7 +297,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/windows_path.html b/proc/windows_path.html index f602e16a6b..54972d7d31 100644 --- a/proc/windows_path.html +++ b/proc/windows_path.html @@ -162,7 +162,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -238,7 +238,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/with_qp.html b/proc/with_qp.html index 1f573816f6..9073cc2360 100644 --- a/proc/with_qp.html +++ b/proc/with_qp.html @@ -164,7 +164,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -230,7 +230,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/with_xdp.html b/proc/with_xdp.html index 570dc07e31..b6a8589495 100644 --- a/proc/with_xdp.html +++ b/proc/with_xdp.html @@ -164,7 +164,7 @@

    Arguments

    - + class(compiler_t), intent(in) @@ -230,7 +230,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/proc/write_response_file.html b/proc/write_response_file.html index 35037c30d4..305f943a61 100644 --- a/proc/write_response_file.html +++ b/proc/write_response_file.html @@ -118,7 +118,7 @@

    Variables

    iarg - io + io
    @@ -177,7 +177,7 @@

    Arguments

    - + character(len=*), intent(in) @@ -242,7 +242,7 @@

    Variables

    - + integer, public @@ -308,7 +308,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/program/main.html b/program/main.html index b1c065300e..73622a0d95 100644 --- a/program/main.html +++ b/program/main.html @@ -116,7 +116,7 @@

    Variables

    @@ -185,16 +185,16 @@

    Uses

    -

    subroutine handle_error(error_) +

    subroutine handle_error(error_)

    @@ -626,7 +626,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/search.html b/search.html index 278c639b4e..69fe693895 100644 --- a/search.html +++ b/search.html @@ -102,7 +102,7 @@

    Search Results

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/build.f90.html b/sourcefile/build.f90.html index 4b9acb50a3..488748a05f 100644 --- a/sourcefile/build.f90.html +++ b/sourcefile/build.f90.html @@ -502,7 +502,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/dependency.f90.html b/sourcefile/dependency.f90.html index 48237518ae..f0f1640517 100644 --- a/sourcefile/dependency.f90.html +++ b/sourcefile/dependency.f90.html @@ -731,7 +731,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/dependency.f90~2.html b/sourcefile/dependency.f90~2.html index 4a6e276738..86e3e27369 100644 --- a/sourcefile/dependency.f90~2.html +++ b/sourcefile/dependency.f90~2.html @@ -1731,7 +1731,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/downloader.f90.html b/sourcefile/downloader.f90.html index 0d84ba01e8..8206b0844d 100644 --- a/sourcefile/downloader.f90.html +++ b/sourcefile/downloader.f90.html @@ -307,7 +307,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/error.f90.html b/sourcefile/error.f90.html index 592c7b9f45..b3ca8035c4 100644 --- a/sourcefile/error.f90.html +++ b/sourcefile/error.f90.html @@ -358,7 +358,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/example.f90.html b/sourcefile/example.f90.html index 1f0039c876..e55b9a6a88 100644 --- a/sourcefile/example.f90.html +++ b/sourcefile/example.f90.html @@ -353,7 +353,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/executable.f90.html b/sourcefile/executable.f90.html index d21c161a11..fc7237c23b 100644 --- a/sourcefile/executable.f90.html +++ b/sourcefile/executable.f90.html @@ -524,7 +524,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/export.f90.html b/sourcefile/export.f90.html index 0a3efccb10..ab428bd050 100644 --- a/sourcefile/export.f90.html +++ b/sourcefile/export.f90.html @@ -258,7 +258,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fortran.f90.html b/sourcefile/fortran.f90.html index 8920987f1e..abbeee8ac2 100644 --- a/sourcefile/fortran.f90.html +++ b/sourcefile/fortran.f90.html @@ -353,7 +353,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm.f90.html b/sourcefile/fpm.f90.html index fc23af06c1..661b48ff50 100644 --- a/sourcefile/fpm.f90.html +++ b/sourcefile/fpm.f90.html @@ -969,7 +969,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_backend.f90.html b/sourcefile/fpm_backend.f90.html index 243d5555fa..acc016aac4 100644 --- a/sourcefile/fpm_backend.f90.html +++ b/sourcefile/fpm_backend.f90.html @@ -551,7 +551,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_backend_console.f90.html b/sourcefile/fpm_backend_console.f90.html index 9f24ad778e..7fb20049c2 100644 --- a/sourcefile/fpm_backend_console.f90.html +++ b/sourcefile/fpm_backend_console.f90.html @@ -288,7 +288,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_backend_output.f90.html b/sourcefile/fpm_backend_output.f90.html index 5c15a9ff3b..e3602d885a 100644 --- a/sourcefile/fpm_backend_output.f90.html +++ b/sourcefile/fpm_backend_output.f90.html @@ -353,7 +353,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_command_line.f90.html b/sourcefile/fpm_command_line.f90.html index 01ffcb1fd9..9156dae4b9 100644 --- a/sourcefile/fpm_command_line.f90.html +++ b/sourcefile/fpm_command_line.f90.html @@ -1745,7 +1745,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_compiler.f90.html b/sourcefile/fpm_compiler.f90.html index 40cbabf287..6ded13f3c9 100644 --- a/sourcefile/fpm_compiler.f90.html +++ b/sourcefile/fpm_compiler.f90.html @@ -1675,7 +1675,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_environment.f90.html b/sourcefile/fpm_environment.f90.html index f5b1c3e113..7966bc140b 100644 --- a/sourcefile/fpm_environment.f90.html +++ b/sourcefile/fpm_environment.f90.html @@ -615,7 +615,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_filesystem.f90.html b/sourcefile/fpm_filesystem.f90.html index 43852fcd17..986eac6bf4 100644 --- a/sourcefile/fpm_filesystem.f90.html +++ b/sourcefile/fpm_filesystem.f90.html @@ -1433,7 +1433,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_meta.f90.html b/sourcefile/fpm_meta.f90.html index d6615de7a2..d1e356612e 100644 --- a/sourcefile/fpm_meta.f90.html +++ b/sourcefile/fpm_meta.f90.html @@ -2079,7 +2079,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_model.f90.html b/sourcefile/fpm_model.f90.html index d955d4291b..9c645e7378 100644 --- a/sourcefile/fpm_model.f90.html +++ b/sourcefile/fpm_model.f90.html @@ -208,7 +208,7 @@

    Source Code

    FPM_UNIT_SUBMODULE, FPM_UNIT_SUBPROGRAM, FPM_UNIT_CSOURCE, & FPM_UNIT_CHEADER, FPM_SCOPE_UNKNOWN, FPM_SCOPE_LIB, & FPM_SCOPE_DEP, FPM_SCOPE_APP, FPM_SCOPE_EXAMPLE, FPM_SCOPE_TEST, & - FPM_UNIT_CPPSOURCE, FPM_SCOPE_NAME + FPM_UNIT_CPPSOURCE, FPM_SCOPE_NAME, FPM_UNIT_NAME !> Source type unknown integer, parameter :: FPM_UNIT_UNKNOWN = -1 @@ -1258,7 +1258,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_os.f90.html b/sourcefile/fpm_os.f90.html index c11b381e70..367f15106a 100644 --- a/sourcefile/fpm_os.f90.html +++ b/sourcefile/fpm_os.f90.html @@ -433,7 +433,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_pkg_config.f90.html b/sourcefile/fpm_pkg_config.f90.html index b66f20d940..9745a9afb8 100644 --- a/sourcefile/fpm_pkg_config.f90.html +++ b/sourcefile/fpm_pkg_config.f90.html @@ -523,7 +523,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_release.f90.html b/sourcefile/fpm_release.f90.html index 11cb8810a1..734baf2d8e 100644 --- a/sourcefile/fpm_release.f90.html +++ b/sourcefile/fpm_release.f90.html @@ -221,7 +221,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_settings.f90.html b/sourcefile/fpm_settings.f90.html index b0a3d4cfeb..971cd9a56f 100644 --- a/sourcefile/fpm_settings.f90.html +++ b/sourcefile/fpm_settings.f90.html @@ -419,7 +419,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_source_parsing.f90.html b/sourcefile/fpm_source_parsing.f90.html index c6a5c0dd4a..35ff9db5cd 100644 --- a/sourcefile/fpm_source_parsing.f90.html +++ b/sourcefile/fpm_source_parsing.f90.html @@ -490,394 +490,397 @@

    Source Code

    end if ! Detect if contains a program - ! (no modules allowed after program def) - if (index(file_lines_lower(i)%s,'program ') == 1) then - - temp_string = split_n(file_lines_lower(i)%s,n=2,delims=' ',stat=stat) - if (stat == 0) then - - if (scan(temp_string,'=(')>0 ) then - ! Ignore: - ! program =* - ! program (i) =* - cycle - end if - - end if + ! - no modules allowed after program def + ! - program header may be missing (only "end program" statement present) + if (index(file_lines_lower(i)%s,'program ')==1 .or. & + parse_sequence(file_lines_lower(i)%s,'end','program')) then + + temp_string = split_n(file_lines_lower(i)%s,n=2,delims=' ',stat=stat) + if (stat == 0) then + + if (scan(temp_string,'=(')>0 ) then + ! Ignore: + ! program =* + ! program (i) =* + cycle + end if - f_source%unit_type = FPM_UNIT_PROGRAM + end if - cycle + f_source%unit_type = FPM_UNIT_PROGRAM - end if - - ! Parse end module statement - ! (to check for code outside of modules) - if (parse_sequence(file_lines_lower(i)%s,'end','module') .or. & - parse_sequence(file_lines_lower(i)%s,'end','submodule')) then - - inside_module = .false. - cycle + cycle + + + end if + + ! Parse end module statement + ! (to check for code outside of modules) + if (parse_sequence(file_lines_lower(i)%s,'end','module') .or. & + parse_sequence(file_lines_lower(i)%s,'end','submodule')) then - end if - - ! Any statements not yet parsed are assumed to be other code statements - if (.not.inside_module .and. f_source%unit_type /= FPM_UNIT_PROGRAM) then + inside_module = .false. + cycle + + end if - f_source%unit_type = FPM_UNIT_SUBPROGRAM - - end if - - end do file_loop - - ! If unable to parse end of module statement, then can't assume pure module - ! (there could be non-module subprograms present) - if (inside_module .and. f_source%unit_type == FPM_UNIT_MODULE) then - f_source%unit_type = FPM_UNIT_SUBPROGRAM - end if - - if (pass == 1) then - allocate(f_source%modules_used(n_use)) - allocate(f_source%include_dependencies(n_include)) - allocate(f_source%modules_provided(n_mod)) - allocate(f_source%parent_modules(n_parent)) - end if - - end do - -end function parse_f_source - + ! Any statements not yet parsed are assumed to be other code statements + if (.not.inside_module .and. f_source%unit_type /= FPM_UNIT_PROGRAM) then + + f_source%unit_type = FPM_UNIT_SUBPROGRAM + + end if + + end do file_loop + + ! If unable to parse end of module statement, then can't assume pure module + ! (there could be non-module subprograms present) + if (inside_module .and. f_source%unit_type == FPM_UNIT_MODULE) then + f_source%unit_type = FPM_UNIT_SUBPROGRAM + end if + + if (pass == 1) then + allocate(f_source%modules_used(n_use)) + allocate(f_source%include_dependencies(n_include)) + allocate(f_source%modules_provided(n_mod)) + allocate(f_source%parent_modules(n_parent)) + end if + + end do -!> Parsing of c, cpp source files -!> -!> The following statements are recognised and parsed: -!> -!> - `#include` preprocessor statement -!> -function parse_c_source(c_filename,error) result(c_source) - character(*), intent(in) :: c_filename - type(srcfile_t) :: c_source - type(error_t), allocatable, intent(out) :: error - - integer :: fh, n_include, i, pass, stat - type(string_t), allocatable :: file_lines(:) +end function parse_f_source + + +!> Parsing of c, cpp source files +!> +!> The following statements are recognised and parsed: +!> +!> - `#include` preprocessor statement +!> +function parse_c_source(c_filename,error) result(c_source) + character(*), intent(in) :: c_filename + type(srcfile_t) :: c_source + type(error_t), allocatable, intent(out) :: error - c_source%file_name = c_filename - - if (str_ends_with(lower(c_filename), ".c")) then - - c_source%unit_type = FPM_UNIT_CSOURCE - - else if (str_ends_with(lower(c_filename), ".h")) then - - c_source%unit_type = FPM_UNIT_CHEADER - - else if (str_ends_with(lower(c_filename), ".cpp")) then - - c_source%unit_type = FPM_UNIT_CPPSOURCE - - end if - - allocate(c_source%modules_used(0)) - allocate(c_source%modules_provided(0)) - allocate(c_source%parent_modules(0)) - - file_lines = read_lines(c_filename) - - ! Ignore empty files, returned as FPM_UNIT_UNKNOWN - if (len_trim(file_lines) < 1) then - c_source%unit_type = FPM_UNIT_UNKNOWN - return - end if - - c_source%digest = fnv_1a(file_lines) - - do pass = 1,2 - n_include = 0 - file_loop: do i=1,size(file_lines) - - ! Process 'INCLUDE' statements - if (index(adjustl(lower(file_lines(i)%s)),'#include') == 1 .and. & - index(file_lines(i)%s,'"') > 0) then - - n_include = n_include + 1 - - if (pass == 2) then - - c_source%include_dependencies(n_include)%s = & - & split_n(file_lines(i)%s,n=2,delims='"',stat=stat) - if (stat /= 0) then - call file_parse_error(error,c_filename, & - 'unable to get c include file',i, & - file_lines(i)%s,index(file_lines(i)%s,'"')) - return - end if - - end if - - end if - - end do file_loop - - if (pass == 1) then - allocate(c_source%include_dependencies(n_include)) - end if - - end do - -end function parse_c_source - -!> Split a string on one or more delimeters -!> and return the nth substring if it exists -!> -!> n=0 will return the last item -!> n=-1 will return the penultimate item etc. + integer :: fh, n_include, i, pass, stat + type(string_t), allocatable :: file_lines(:) + + c_source%file_name = c_filename + + if (str_ends_with(lower(c_filename), ".c")) then + + c_source%unit_type = FPM_UNIT_CSOURCE + + else if (str_ends_with(lower(c_filename), ".h")) then + + c_source%unit_type = FPM_UNIT_CHEADER + + else if (str_ends_with(lower(c_filename), ".cpp")) then + + c_source%unit_type = FPM_UNIT_CPPSOURCE + + end if + + allocate(c_source%modules_used(0)) + allocate(c_source%modules_provided(0)) + allocate(c_source%parent_modules(0)) + + file_lines = read_lines(c_filename) + + ! Ignore empty files, returned as FPM_UNIT_UNKNOWN + if (len_trim(file_lines) < 1) then + c_source%unit_type = FPM_UNIT_UNKNOWN + return + end if + + c_source%digest = fnv_1a(file_lines) + + do pass = 1,2 + n_include = 0 + file_loop: do i=1,size(file_lines) + + ! Process 'INCLUDE' statements + if (index(adjustl(lower(file_lines(i)%s)),'#include') == 1 .and. & + index(file_lines(i)%s,'"') > 0) then + + n_include = n_include + 1 + + if (pass == 2) then + + c_source%include_dependencies(n_include)%s = & + & split_n(file_lines(i)%s,n=2,delims='"',stat=stat) + if (stat /= 0) then + call file_parse_error(error,c_filename, & + 'unable to get c include file',i, & + file_lines(i)%s,index(file_lines(i)%s,'"')) + return + end if + + end if + + end if + + end do file_loop + + if (pass == 1) then + allocate(c_source%include_dependencies(n_include)) + end if + + end do + +end function parse_c_source + +!> Split a string on one or more delimeters +!> and return the nth substring if it exists !> -!> stat = 1 on return if the index -!> is not found +!> n=0 will return the last item +!> n=-1 will return the penultimate item etc. !> -function split_n(string,delims,n,stat) result(substring) - - character(*), intent(in) :: string - character(*), intent(in) :: delims - integer, intent(in) :: n - integer, intent(out) :: stat - character(:), allocatable :: substring - - integer :: i - character(:), allocatable :: string_parts(:) +!> stat = 1 on return if the index +!> is not found +!> +function split_n(string,delims,n,stat) result(substring) + + character(*), intent(in) :: string + character(*), intent(in) :: delims + integer, intent(in) :: n + integer, intent(out) :: stat + character(:), allocatable :: substring - call split(string,string_parts,delims) - - if (n<1) then - i = size(string_parts) + n - if (i < 1) then - allocate(character(len=0) :: substring) ! ifort bus error otherwise - stat = 1 - return - end if - else - i = n - end if - - if (i>size(string_parts)) then - allocate(character(len=0) :: substring) ! ifort bus error otherwise - stat = 1 - return - end if - - substring = trim(adjustl(string_parts(i))) - stat = 0 + integer :: i + character(:), allocatable :: string_parts(:) + + call split(string,string_parts,delims) + + if (n<1) then + i = size(string_parts) + n + if (i < 1) then + allocate(character(len=0) :: substring) ! ifort bus error otherwise + stat = 1 + return + end if + else + i = n + end if + + if (i>size(string_parts)) then + allocate(character(len=0) :: substring) ! ifort bus error otherwise + stat = 1 + return + end if -end function split_n - + substring = trim(adjustl(string_parts(i))) + stat = 0 -!> Parse a subsequence of blank-separated tokens within a string -!> (see parse_sequence) -function parse_subsequence(string,t1,t2,t3,t4) result(found) - character(*), intent(in) :: string - character(*), intent(in) :: t1 - character(*), intent(in), optional :: t2, t3, t4 - logical :: found - - integer :: offset, i - - found = .false. - offset = 1 +end function split_n + + +!> Parse a subsequence of blank-separated tokens within a string +!> (see parse_sequence) +function parse_subsequence(string,t1,t2,t3,t4) result(found) + character(*), intent(in) :: string + character(*), intent(in) :: t1 + character(*), intent(in), optional :: t2, t3, t4 + logical :: found + + integer :: offset, i - do - - i = index(string(offset:),t1) - - if (i == 0) return - - offset = offset + i - 1 - - found = parse_sequence(string(offset:),t1,t2,t3,t4) - - if (found) return - - offset = offset + len(t1) - - if (offset > len(string)) return - - end do - -end function parse_subsequence - -!> Helper utility to parse sequences of tokens -!> that may be optionally separated by zero or more spaces -function parse_sequence(string,t1,t2,t3,t4) result(found) - character(*), intent(in) :: string - character(*), intent(in) :: t1 - character(*), intent(in), optional :: t2, t3, t4 - logical :: found - - integer :: post, n, incr, pos, token_n - logical :: match + found = .false. + offset = 1 + + do + + i = index(string(offset:),t1) + + if (i == 0) return + + offset = offset + i - 1 + + found = parse_sequence(string(offset:),t1,t2,t3,t4) + + if (found) return + + offset = offset + len(t1) + + if (offset > len(string)) return + + end do + +end function parse_subsequence + +!> Helper utility to parse sequences of tokens +!> that may be optionally separated by zero or more spaces +function parse_sequence(string,t1,t2,t3,t4) result(found) + character(*), intent(in) :: string + character(*), intent(in) :: t1 + character(*), intent(in), optional :: t2, t3, t4 + logical :: found - n = len(string) - found = .false. - pos = 1 - - do token_n=1,4 - - do while (pos <= n) - if (string(pos:pos) /= ' ') then - exit - end if - pos = pos + 1 - end do - - select case(token_n) - case(1) - incr = len(t1) - if (pos+incr-1>n) return - match = string(pos:pos+incr-1) == t1 - case(2) - if (.not.present(t2)) exit - incr = len(t2) - if (pos+incr-1>n) return - match = string(pos:pos+incr-1) == t2 - case(3) - if (.not.present(t3)) exit - incr = len(t3) - if (pos+incr-1>n) return - match = string(pos:pos+incr-1) == t3 - case(4) - if (.not.present(t4)) exit - incr = len(t4) - if (pos+incr-1>n) return - match = string(pos:pos+incr-1) == t4 - case default - exit - end select - - if (.not.match) then - return - end if - - pos = pos + incr - - end do - - found = .true. - -end function parse_sequence - -! USE [, intrinsic] :: module_name [, only: only_list] -! USE [, non_intrinsic] :: module_name [, only: only_list] -subroutine parse_use_statement(f_filename,i,line,use_stmt,is_intrinsic,module_name,error) - - !> Current file name and line number (for error messaging) - character(*), intent(in) :: f_filename - integer, intent(in) :: i - - !> The line being parsed. MUST BE preprocessed with trim(adjustl() - character(*), intent(in) :: line + integer :: post, n, incr, pos, token_n + logical :: match + + n = len(string) + found = .false. + pos = 1 + + do token_n=1,4 + + do while (pos <= n) + if (string(pos:pos) /= ' ') then + exit + end if + pos = pos + 1 + end do + + select case(token_n) + case(1) + incr = len(t1) + if (pos+incr-1>n) return + match = string(pos:pos+incr-1) == t1 + case(2) + if (.not.present(t2)) exit + incr = len(t2) + if (pos+incr-1>n) return + match = string(pos:pos+incr-1) == t2 + case(3) + if (.not.present(t3)) exit + incr = len(t3) + if (pos+incr-1>n) return + match = string(pos:pos+incr-1) == t3 + case(4) + if (.not.present(t4)) exit + incr = len(t4) + if (pos+incr-1>n) return + match = string(pos:pos+incr-1) == t4 + case default + exit + end select + + if (.not.match) then + return + end if + + pos = pos + incr + + end do + + found = .true. + +end function parse_sequence + +! USE [, intrinsic] :: module_name [, only: only_list] +! USE [, non_intrinsic] :: module_name [, only: only_list] +subroutine parse_use_statement(f_filename,i,line,use_stmt,is_intrinsic,module_name,error) + + !> Current file name and line number (for error messaging) + character(*), intent(in) :: f_filename + integer, intent(in) :: i - !> Does this line contain a `use` statement? - logical, intent(out) :: use_stmt + !> The line being parsed. MUST BE preprocessed with trim(adjustl() + character(*), intent(in) :: line - !> Is the module in this statement intrinsic? - logical, intent(out) :: is_intrinsic + !> Does this line contain a `use` statement? + logical, intent(out) :: use_stmt - !> used module name - character(:), allocatable, intent(out) :: module_name + !> Is the module in this statement intrinsic? + logical, intent(out) :: is_intrinsic - !> Error handling - type(error_t), allocatable, intent(out) :: error + !> used module name + character(:), allocatable, intent(out) :: module_name - character(15), parameter :: INTRINSIC_NAMES(*) = & - ['iso_c_binding ', & - 'iso_fortran_env', & - 'ieee_arithmetic', & - 'ieee_exceptions', & - 'ieee_features ', & - 'omp_lib '] - - character(len=:), allocatable :: temp_string - integer :: colons,intr,nonintr,j,stat - logical :: has_intrinsic_name - - use_stmt = .false. - is_intrinsic = .false. - if (len_trim(line)<=0) return - - ! Quick check that the line is preprocessed - if (line(1:1)==' ') then - call fatal_error(error,'internal_error: source file line is not trim(adjustl()) on input to parse_use_statement') - return - end if - - ! 'use' should be the first string in the adjustl line - use_stmt = index(line,'use ')==1 .or. index(line,'use::')==1 .or. index(line,'use,')==1 - if (.not.use_stmt) return - colons = index(line,'::') - nonintr = 0 - intr = 0 - - have_colons: if (colons>3) then - - ! there may be an intrinsic/non-intrinsic spec - nonintr = index(line(1:colons-1),'non_intrinsic') - if (nonintr==0) intr = index(line(1:colons-1),'intrinsic') - - - temp_string = split_n(line,delims=':',n=2,stat=stat) - if (stat /= 0) then - call file_parse_error(error,f_filename, & - 'unable to find used module name',i, & - line,colons) - return - end if - - module_name = split_n(temp_string,delims=' ,',n=1,stat=stat) - if (stat /= 0) then - call file_parse_error(error,f_filename, & - 'unable to find used module name',i, & - line) - return - end if - - else - - module_name = split_n(line,n=2,delims=' ,',stat=stat) - if (stat /= 0) then - call file_parse_error(error,f_filename, & - 'unable to find used module name',i, & - line) - return - end if - - end if have_colons - - ! If declared intrinsic, check that it is true - has_intrinsic_name = any([(index(module_name,trim(INTRINSIC_NAMES(j)))>0, & - j=1,size(INTRINSIC_NAMES))]) - if (intr>0 .and. .not.has_intrinsic_name) then - - ! An intrinsic module was not found. Its name could be in the next line, - ! in which case, we just skip this check. The compiler will do the job if the name is invalid. + !> Error handling + type(error_t), allocatable, intent(out) :: error + + character(15), parameter :: INTRINSIC_NAMES(*) = & + ['iso_c_binding ', & + 'iso_fortran_env', & + 'ieee_arithmetic', & + 'ieee_exceptions', & + 'ieee_features ', & + 'omp_lib '] + + character(len=:), allocatable :: temp_string + integer :: colons,intr,nonintr,j,stat + logical :: has_intrinsic_name + + use_stmt = .false. + is_intrinsic = .false. + if (len_trim(line)<=0) return + + ! Quick check that the line is preprocessed + if (line(1:1)==' ') then + call fatal_error(error,'internal_error: source file line is not trim(adjustl()) on input to parse_use_statement') + return + end if + + ! 'use' should be the first string in the adjustl line + use_stmt = index(line,'use ')==1 .or. index(line,'use::')==1 .or. index(line,'use,')==1 + if (.not.use_stmt) return + colons = index(line,'::') + nonintr = 0 + intr = 0 + + have_colons: if (colons>3) then + + ! there may be an intrinsic/non-intrinsic spec + nonintr = index(line(1:colons-1),'non_intrinsic') + if (nonintr==0) intr = index(line(1:colons-1),'intrinsic') + + + temp_string = split_n(line,delims=':',n=2,stat=stat) + if (stat /= 0) then + call file_parse_error(error,f_filename, & + 'unable to find used module name',i, & + line,colons) + return + end if + + module_name = split_n(temp_string,delims=' ,',n=1,stat=stat) + if (stat /= 0) then + call file_parse_error(error,f_filename, & + 'unable to find used module name',i, & + line) + return + end if + + else + + module_name = split_n(line,n=2,delims=' ,',stat=stat) + if (stat /= 0) then + call file_parse_error(error,f_filename, & + 'unable to find used module name',i, & + line) + return + end if + + end if have_colons + + ! If declared intrinsic, check that it is true + has_intrinsic_name = any([(index(module_name,trim(INTRINSIC_NAMES(j)))>0, & + j=1,size(INTRINSIC_NAMES))]) + if (intr>0 .and. .not.has_intrinsic_name) then - ! Module name was not read: it's in the next line - if (index(module_name,'&')<=0) then - call file_parse_error(error,f_filename, & - 'module '//module_name//' is declared intrinsic but it is not ',i, & - line) - return - endif - endif - - ! Should we treat this as an intrinsic module - is_intrinsic = nonintr==0 .and. & ! not declared non-intrinsic - (intr>0 .or. has_intrinsic_name) - -end subroutine parse_use_statement - + ! An intrinsic module was not found. Its name could be in the next line, + ! in which case, we just skip this check. The compiler will do the job if the name is invalid. + + ! Module name was not read: it's in the next line + if (index(module_name,'&')<=0) then + call file_parse_error(error,f_filename, & + 'module '//module_name//' is declared intrinsic but it is not ',i, & + line) + return + endif + endif + + ! Should we treat this as an intrinsic module + is_intrinsic = nonintr==0 .and. & ! not declared non-intrinsic + (intr>0 .or. has_intrinsic_name) - -end module fpm_source_parsing +end subroutine parse_use_statement + + + +end module fpm_source_parsing @@ -899,7 +902,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_sources.f90.html b/sourcefile/fpm_sources.f90.html index 07fd4b88ff..31b53e5a35 100644 --- a/sourcefile/fpm_sources.f90.html +++ b/sourcefile/fpm_sources.f90.html @@ -466,7 +466,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_strings.f90.html b/sourcefile/fpm_strings.f90.html index c168a92be7..e2dfcbed3b 100644 --- a/sourcefile/fpm_strings.f90.html +++ b/sourcefile/fpm_strings.f90.html @@ -1792,7 +1792,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/fpm_targets.f90.html b/sourcefile/fpm_targets.f90.html index 17e6f688f0..ed04d19485 100644 --- a/sourcefile/fpm_targets.f90.html +++ b/sourcefile/fpm_targets.f90.html @@ -1283,7 +1283,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/git.f90.html b/sourcefile/git.f90.html index 22dc6e50f9..ef9a4ce73a 100644 --- a/sourcefile/git.f90.html +++ b/sourcefile/git.f90.html @@ -630,7 +630,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/install.f90.html b/sourcefile/install.f90.html index dab9cab534..3108a9f3b2 100644 --- a/sourcefile/install.f90.html +++ b/sourcefile/install.f90.html @@ -344,7 +344,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/install.f90~2.html b/sourcefile/install.f90~2.html index c9ceb71c80..b53f7ab730 100644 --- a/sourcefile/install.f90~2.html +++ b/sourcefile/install.f90~2.html @@ -329,7 +329,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/installer.f90.html b/sourcefile/installer.f90.html index 126362eb14..82ad569603 100644 --- a/sourcefile/installer.f90.html +++ b/sourcefile/installer.f90.html @@ -453,7 +453,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/library.f90.html b/sourcefile/library.f90.html index 633bc415ea..46544145dc 100644 --- a/sourcefile/library.f90.html +++ b/sourcefile/library.f90.html @@ -389,7 +389,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/main.f90.html b/sourcefile/main.f90.html index 2c62776273..e24641699c 100644 --- a/sourcefile/main.f90.html +++ b/sourcefile/main.f90.html @@ -302,7 +302,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/manifest.f90.html b/sourcefile/manifest.f90.html index e065df67a9..56c9e4d1ee 100644 --- a/sourcefile/manifest.f90.html +++ b/sourcefile/manifest.f90.html @@ -360,7 +360,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/meta.f90.html b/sourcefile/meta.f90.html index 1f5a7618f7..448ebb0f6e 100644 --- a/sourcefile/meta.f90.html +++ b/sourcefile/meta.f90.html @@ -402,7 +402,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/new.f90.html b/sourcefile/new.f90.html index e030b7147a..063ffe556a 100644 --- a/sourcefile/new.f90.html +++ b/sourcefile/new.f90.html @@ -877,7 +877,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/package.f90.html b/sourcefile/package.f90.html index 9c45293f19..5febc4b079 100644 --- a/sourcefile/package.f90.html +++ b/sourcefile/package.f90.html @@ -1260,7 +1260,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/preprocess.f90.html b/sourcefile/preprocess.f90.html index c6d42bdb04..a9fb87406e 100644 --- a/sourcefile/preprocess.f90.html +++ b/sourcefile/preprocess.f90.html @@ -517,7 +517,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/profiles.f90.html b/sourcefile/profiles.f90.html index dc1b23d4a6..b0114560a0 100644 --- a/sourcefile/profiles.f90.html +++ b/sourcefile/profiles.f90.html @@ -1414,7 +1414,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/publish.f90.html b/sourcefile/publish.f90.html index 93f268491e..4b87b12b7a 100644 --- a/sourcefile/publish.f90.html +++ b/sourcefile/publish.f90.html @@ -295,7 +295,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/test.f90.html b/sourcefile/test.f90.html index e1c99d6ab5..7aeaa76f5d 100644 --- a/sourcefile/test.f90.html +++ b/sourcefile/test.f90.html @@ -353,7 +353,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/toml.f90.html b/sourcefile/toml.f90.html index b759cd259d..8bab2397fe 100644 --- a/sourcefile/toml.f90.html +++ b/sourcefile/toml.f90.html @@ -954,7 +954,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/update.f90.html b/sourcefile/update.f90.html index 25d26968bc..e485d6601c 100644 --- a/sourcefile/update.f90.html +++ b/sourcefile/update.f90.html @@ -252,7 +252,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/sourcefile/versioning.f90.html b/sourcefile/versioning.f90.html index 9bec2c045a..7103e062ef 100644 --- a/sourcefile/versioning.f90.html +++ b/sourcefile/versioning.f90.html @@ -617,7 +617,7 @@

    Source Code

    Documentation generated by FORD - on 2024-10-21 16:25

    + on 2024-10-21 16:43


    diff --git a/src/fpm_model.f90 b/src/fpm_model.f90 index f3449e16d2..2db459f26f 100644 --- a/src/fpm_model.f90 +++ b/src/fpm_model.f90 @@ -52,7 +52,7 @@ module fpm_model FPM_UNIT_SUBMODULE, FPM_UNIT_SUBPROGRAM, FPM_UNIT_CSOURCE, & FPM_UNIT_CHEADER, FPM_SCOPE_UNKNOWN, FPM_SCOPE_LIB, & FPM_SCOPE_DEP, FPM_SCOPE_APP, FPM_SCOPE_EXAMPLE, FPM_SCOPE_TEST, & - FPM_UNIT_CPPSOURCE, FPM_SCOPE_NAME + FPM_UNIT_CPPSOURCE, FPM_SCOPE_NAME, FPM_UNIT_NAME !> Source type unknown integer, parameter :: FPM_UNIT_UNKNOWN = -1 diff --git a/src/fpm_source_parsing.f90 b/src/fpm_source_parsing.f90 index c1f4bab98f..4032292006 100644 --- a/src/fpm_source_parsing.f90 +++ b/src/fpm_source_parsing.f90 @@ -334,8 +334,10 @@ function parse_f_source(f_filename,error) result(f_source) end if ! Detect if contains a program - ! (no modules allowed after program def) - if (index(file_lines_lower(i)%s,'program ') == 1) then + ! - no modules allowed after program def + ! - program header may be missing (only "end program" statement present) + if (index(file_lines_lower(i)%s,'program ')==1 .or. & + parse_sequence(file_lines_lower(i)%s,'end','program')) then temp_string = split_n(file_lines_lower(i)%s,n=2,delims=' ',stat=stat) if (stat == 0) then @@ -352,6 +354,7 @@ function parse_f_source(f_filename,error) result(f_source) f_source%unit_type = FPM_UNIT_PROGRAM cycle + end if diff --git a/tipuesearch/tipuesearch_content.js b/tipuesearch/tipuesearch_content.js index 6b9e277487..6b94910fe8 100644 --- a/tipuesearch/tipuesearch_content.js +++ b/tipuesearch/tipuesearch_content.js @@ -1 +1 @@ -var tipuesearch = {"pages":[{"title":" Fortran-lang/fpm ","text":"Fortran-lang/fpm Fortran package manager developer documentation The package manifest Command line interface The package model The build backend Generating this documentation Fortran package manager developer documentation This is the main documentation of the Fortran package manager ( fpm ).\nThis document serves as developer documentation of fpm itself and contains general advice for developing in the fpm code base. The package manifest The central object describing an fpm project is the package manifest fpm.toml .\nThe manifest is written in TOML, you can find the TOML specification at the official TOML homepage . The fpm.toml file targets project developers and maintainers to relieve them from writing build files for their packages.\nWith the package manifest a central place to collect information about the project is provided.\nIt contains the versioning and licensing meta data, as well as the information on external dependencies and the required build-tools or compiler settings. The manifest format specific to fpm projects is documented in the manifest reference . Note For a more practical but less complete guide on creating fpm projects see the packaging guide . The details of the TOML parsing are implemented with using the tomlf module.\nGenerally, the interface to all TOML related functions for fpm is found in the proxy module fpm_toml . All the manifest types are bundled in fpm_manifest .\nWhile the specific subtables for the package configuration are found in the src/fpm/manifest directory, they should be reexported in the fpm_manifest module if they should be elsewhere in fpm . Command line interface fpm is mainly used as a command line tool.\nTo work with an fpm project as a user you can completely rely on the command line. The command line interface is build with the M_CLI2 module and can be found in fpm_command_line . The package model Once front-end inputs have been received from the package manifest and command line interface, fpm will construct an\ninternal representation of the package and its dependencies. This internal representation is known as the package model .\nThe model and its associated data types should encapsulate all the information required to correctly build a package and\nshould be independent of the intended backend build system. Information stored in the model includes: build targets and\ntheir inter-dependencies; compiler and compiler flags; library linking information. For more information on the contents of the package model and the process for constructing it, please see fpm_model . The build backend Once a complete package model has been constructed, it can be passed to a backend for either performing the compilation\nand linking of targets, or for generating configuration files for a third-party build system.\nCurrently, only a native backend is implemented in fpm . See fpm_backend for more information. Generating this documentation This documentation is generated by FORD .\nFor more details on the project file and the comment markup in the source code visit the FORD documentation . To regenerate this documentation run: ford docs.md Developer Info fortran-lang/fpm contributors","tags":"home","loc":"index.html"},{"title":"install_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: install_config_t Configuration data for installation Components Type Visibility Attributes Name Initial logical, public :: library = .false. Install library with this project Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Arguments Type Intent Optional Attributes Name class( install_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on install configuration instance Arguments Type Intent Optional Attributes Name class( install_config_t ), intent(in) :: self Instance of the build configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( install_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => install_conf_same Serialization interface private function install_conf_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( install_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: install_config_t !> Install library with this project logical :: library = . false . contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => install_conf_same procedure :: dump_to_toml procedure :: load_from_toml end type install_config_t","tags":"","loc":"type/install_config_t.html"},{"title":"build_target_ptr – Fortran-lang/fpm ","text":"type, public :: build_target_ptr Wrapper type for constructing arrays of [[build_target_t]] pointers Components Type Visibility Attributes Name Initial type( build_target_t ), public, pointer :: ptr => null() Source Code type build_target_ptr type ( build_target_t ), pointer :: ptr => null () end type build_target_ptr","tags":"","loc":"type/build_target_ptr.html"},{"title":"build_target_t – Fortran-lang/fpm ","text":"type, public :: build_target_t Type describing a generated build target Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: compile_flags Compile flags for this build target type( build_target_ptr ), public, allocatable :: dependencies (:) Resolved build dependencies integer(kind=int64), public, allocatable :: digest_cached Previous source file hash type( fortran_features_t ), public :: features Language features character(len=:), public, allocatable :: link_flags Link flags for this build target type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public, allocatable :: link_objects (:) Objects needed to link this target type( string_t ), public, allocatable :: macros (:) List of macros character(len=:), public, allocatable :: output_dir File path of output directory character(len=:), public, allocatable :: output_file File path of build target object relative to cwd character(len=:), public, allocatable :: output_log_file File path of build log file relative to cwd character(len=:), public, allocatable :: output_name File path of build target object relative to output_dir character(len=:), public, allocatable :: package_name Name of parent package integer, public :: schedule = -1 Targets in the same schedule group are guaranteed to be independent logical, public :: skip = .false. Flag set if build target will be skipped (not built) logical, public :: sorted = .false. Flag set if build target is sorted for building type( srcfile_t ), public, allocatable :: source Primary source for this build target integer, public :: target_type = FPM_TARGET_UNKNOWN Target type logical, public :: touched = .false. Flag set when first visited to check for circular dependencies character(len=:), public, allocatable :: version Version number Type-Bound Procedures procedure, public :: is_executable_target private elemental function is_executable_target(target_ptr, scope) result(is_exe) Arguments Type Intent Optional Attributes Name class( build_target_t ), intent(in) :: target_ptr integer, intent(in) :: scope Return Value logical Source Code type build_target_t !> File path of build target object relative to cwd character (:), allocatable :: output_file !> File path of build target object relative to output_dir character (:), allocatable :: output_name !> File path of output directory character (:), allocatable :: output_dir !> File path of build log file relative to cwd character (:), allocatable :: output_log_file !> Name of parent package character (:), allocatable :: package_name !> Primary source for this build target type ( srcfile_t ), allocatable :: source !> Resolved build dependencies type ( build_target_ptr ), allocatable :: dependencies (:) !> Target type integer :: target_type = FPM_TARGET_UNKNOWN !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> Objects needed to link this target type ( string_t ), allocatable :: link_objects (:) !> Link flags for this build target character (:), allocatable :: link_flags !> Compile flags for this build target character (:), allocatable :: compile_flags !> Flag set when first visited to check for circular dependencies logical :: touched = . false . !> Flag set if build target is sorted for building logical :: sorted = . false . !> Flag set if build target will be skipped (not built) logical :: skip = . false . !> Language features type ( fortran_features_t ) :: features !> Targets in the same schedule group are guaranteed to be independent integer :: schedule = - 1 !> Previous source file hash integer ( int64 ), allocatable :: digest_cached !> List of macros type ( string_t ), allocatable :: macros (:) !> Version number character (:), allocatable :: version contains procedure :: is_executable_target end type build_target_t","tags":"","loc":"type/build_target_t.html"},{"title":"file_scope_flag – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: file_scope_flag Type storing file name - file scope compiler flags pairs Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: file_name Name of the file character(len=:), public, allocatable :: flags File scope flags Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => file_scope_dump public subroutine file_scope_dump (self, table, error) Dump to toml table Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => file_scope_load public subroutine file_scope_load (self, table, error) Read from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => file_scope_same Serialization interface public function file_scope_same (this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: file_scope_flag !> Name of the file character ( len = :), allocatable :: file_name !> File scope flags character ( len = :), allocatable :: flags contains !> Serialization interface procedure :: serializable_is_same => file_scope_same procedure :: dump_to_toml => file_scope_dump procedure :: load_from_toml => file_scope_load end type file_scope_flag","tags":"","loc":"type/file_scope_flag.html"},{"title":"profile_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: profile_config_t Configuration meta data for a profile Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: c_flags C compiler flags character(len=:), public, allocatable :: compiler Name of the compiler character(len=:), public, allocatable :: cxx_flags C++ compiler flags type( file_scope_flag ), public, allocatable :: file_scope_flags (:) File scope flags character(len=:), public, allocatable :: flags Fortran compiler flags logical, public :: is_built_in = .false. Is this profile one of the built-in ones? character(len=:), public, allocatable :: link_time_flags Link time compiler flags integer, public :: os_type = OS_ALL Value repesenting OS character(len=:), public, allocatable :: profile_name Name of the profile Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => profile_dump public subroutine profile_dump (self, table, error) Dump to toml table Read more… Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance public subroutine info (self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: self Instance of the profile configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => profile_load public subroutine profile_load (self, table, error) Read from toml table (no checks made at this stage) Read more… Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => profile_same Serialization interface public function profile_same (this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: profile_config_t !> Name of the profile character ( len = :), allocatable :: profile_name !> Name of the compiler character ( len = :), allocatable :: compiler !> Value repesenting OS integer :: os_type = OS_ALL !> Fortran compiler flags character ( len = :), allocatable :: flags !> C compiler flags character ( len = :), allocatable :: c_flags !> C++ compiler flags character ( len = :), allocatable :: cxx_flags !> Link time compiler flags character ( len = :), allocatable :: link_time_flags !> File scope flags type ( file_scope_flag ), allocatable :: file_scope_flags (:) !> Is this profile one of the built-in ones? logical :: is_built_in = . false . contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => profile_same procedure :: dump_to_toml => profile_dump procedure :: load_from_toml => profile_load end type profile_config_t","tags":"","loc":"type/profile_config_t.html"},{"title":"console_t – Fortran-lang/fpm ","text":"type, public :: console_t Console object Components Type Visibility Attributes Name Initial integer, public :: n_line = 1 Number of lines printed Type-Bound Procedures procedure, public :: update_line => console_update_line Update a previously-written console line private subroutine console_update_line(console, line_no, str) Overwrite a previously-written line in standard output Arguments Type Intent Optional Attributes Name class( console_t ), intent(in) :: console Console object integer, intent(in) :: line_no Integer output from [[console_write_line]] character(len=*), intent(in) :: str New string to overwrite line procedure, public :: write_line => console_write_line Write a single line to the console private subroutine console_write_line(console, str, line, advance) Write a single line to the standard output Arguments Type Intent Optional Attributes Name class( console_t ), intent(inout) :: console Console object character(len=*), intent(in) :: str String to write integer, intent(out), optional :: line Integer needed to later update console line logical, intent(in), optional :: advance Advancing output (print newline?) Source Code type console_t !> Number of lines printed integer :: n_line = 1 contains !> Write a single line to the console procedure :: write_line => console_write_line !> Update a previously-written console line procedure :: update_line => console_update_line end type console_t","tags":"","loc":"type/console_t.html"},{"title":"fortran_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: fortran_config_t Configuration data for Fortran Components Type Visibility Attributes Name Initial logical, public :: implicit_external = .false. Enable implicit external interfaces logical, public :: implicit_typing = .false. Enable default implicit typing character(len=:), public, allocatable :: source_form Form to use for all Fortran sources Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Arguments Type Intent Optional Attributes Name class( fortran_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( fortran_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => fortran_is_same Serialization interface private function fortran_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( fortran_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: fortran_config_t !> Enable default implicit typing logical :: implicit_typing = . false . !> Enable implicit external interfaces logical :: implicit_external = . false . !> Form to use for all Fortran sources character (:), allocatable :: source_form contains !> Serialization interface procedure :: serializable_is_same => fortran_is_same procedure :: dump_to_toml procedure :: load_from_toml end type fortran_config_t","tags":"","loc":"type/fortran_config_t.html"},{"title":"serializable_t – Fortran-lang/fpm ","text":"type, public, abstract :: serializable_t An abstract interface for any fpm class that should be fully serializable to/from TOML/JSON Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure(to_toml), public, deferred :: dump_to_toml Dump to TOML table, unit, file subroutine to_toml(self, table, error) Prototype Write object to TOML datastructure Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure(from_toml), public, deferred :: load_from_toml Load from TOML table, unit, file subroutine from_toml(self, table, error) Prototype Read dependency tree from TOML data structure Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure(is_equal), public, deferred :: serializable_is_same Serializable entities need a way to check that they’re equal function is_equal(this, that) Prototype Compare two serializable objects Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , abstract , public :: serializable_t contains !> Dump to TOML table, unit, file procedure ( to_toml ), deferred :: dump_to_toml procedure , non_overridable , private :: dump_to_file procedure , non_overridable , private :: dump_to_unit generic :: dump => dump_to_toml , dump_to_file , dump_to_unit !> Load from TOML table, unit, file procedure ( from_toml ), deferred :: load_from_toml procedure , non_overridable , private :: load_from_file procedure , non_overridable , private :: load_from_unit generic :: load => load_from_toml , load_from_file , load_from_unit !> Serializable entities need a way to check that they're equal procedure ( is_equal ), deferred :: serializable_is_same generic :: operator ( == ) => serializable_is_same !> Test load/write roundtrip procedure , non_overridable :: test_serialization end type serializable_t","tags":"","loc":"type/serializable_t.html"},{"title":"installer_t – Fortran-lang/fpm ","text":"type, public :: installer_t Declaration of the installer type Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: bindir Binary dir relative to the installation prefix character(len=:), public, allocatable :: copy Command to copy objects into the installation prefix character(len=:), public, allocatable :: includedir Include directory relative to the installation prefix character(len=:), public, allocatable :: libdir Library directory relative to the installation prefix character(len=:), public, allocatable :: move Command to move objects into the installation prefix integer, public :: os Cached operating system character(len=:), public, allocatable :: prefix Path to installation directory integer, public :: unit = output_unit Output unit for informative printout integer, public :: verbosity = 1 Verbosity of the installer Type-Bound Procedures procedure, public :: install Install a generic file into a subdirectory in the installation prefix private subroutine install(self, source, destination, error) Install a generic file into a subdirectory in the installation prefix Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: source Path to the original file character(len=*), intent(in) :: destination Path to the destination inside the prefix type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: install_executable Install an executable in its correct subdirectory private subroutine install_executable(self, executable, error) Install an executable in its correct subdirectory Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: executable Path to the executable type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: install_header Install a header/module in its correct subdirectory private subroutine install_header(self, header, error) Install a header/module in its correct subdirectory Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: header Path to the header type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: install_library Install a library in its correct subdirectory private subroutine install_library(self, library, error) Install a library in its correct subdirectory Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: library Path to the library type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: make_dir Create a new directory in the prefix, type-bound for unit testing purposes private subroutine make_dir(self, dir, error) Create a new directory in the prefix Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: dir Directory to be created type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: run Run an installation command, type-bound for unit testing purposes private subroutine run(self, command, error) Run an installation command Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: command Command to be launched type( error_t ), intent(out), allocatable :: error Error handling Source Code type :: installer_t !> Path to installation directory character ( len = :), allocatable :: prefix !> Binary dir relative to the installation prefix character ( len = :), allocatable :: bindir !> Library directory relative to the installation prefix character ( len = :), allocatable :: libdir !> Include directory relative to the installation prefix character ( len = :), allocatable :: includedir !> Output unit for informative printout integer :: unit = output_unit !> Verbosity of the installer integer :: verbosity = 1 !> Command to copy objects into the installation prefix character ( len = :), allocatable :: copy !> Command to move objects into the installation prefix character ( len = :), allocatable :: move !> Cached operating system integer :: os contains !> Install an executable in its correct subdirectory procedure :: install_executable !> Install a library in its correct subdirectory procedure :: install_library !> Install a header/module in its correct subdirectory procedure :: install_header !> Install a generic file into a subdirectory in the installation prefix procedure :: install !> Run an installation command, type-bound for unit testing purposes procedure :: run !> Create a new directory in the prefix, type-bound for unit testing purposes procedure :: make_dir end type installer_t","tags":"","loc":"type/installer_t.html"},{"title":"string_t – Fortran-lang/fpm ","text":"type, public :: string_t Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: s Constructor public interface string_t private function new_string_t(s) result(string) Helper function to generate a new string_t instance\n (Required due to the allocatable component) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s Return Value type( string_t )","tags":"","loc":"type/string_t.html"},{"title":"metapackage_t – Fortran-lang/fpm ","text":"type, public :: metapackage_t Type for describing a source file Components Type Visibility Attributes Name Initial type( string_t ), public :: cflags type( string_t ), public :: cxxflags type( dependency_config_t ), public, allocatable :: dependency (:) List of Development dependency meta data.\nMetapackage dependencies are never exported from the model type( string_t ), public, allocatable :: external_modules (:) type( string_t ), public :: fflags type( string_t ), public :: flags List of compiler flags and options to be added type( fortran_features_t ), public, allocatable :: fortran Special fortran features logical, public :: has_build_flags = .false. logical, public :: has_c_flags = .false. logical, public :: has_cxx_flags = .false. logical, public :: has_dependencies = .false. logical, public :: has_external_modules = .false. logical, public :: has_fortran_flags = .false. logical, public :: has_include_dirs = .false. logical, public :: has_link_flags = .false. logical, public :: has_link_libraries = .false. logical, public :: has_run_command = .false. type( string_t ), public, allocatable :: incl_dirs (:) type( string_t ), public :: link_flags type( string_t ), public, allocatable :: link_libs (:) type( string_t ), public :: run_command type( version_t ), public, allocatable :: version Package version (if supported) Type-Bound Procedures procedure, public :: destroy Clean metapackage structure private elemental subroutine destroy(this) Clean the metapackage structure Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(inout) :: this procedure, public :: new => init_from_name Initialize the metapackage structure from its given name private subroutine init_from_name(this, name, compiler, error) Initialize a metapackage from the given name\nInitialize metapackage by name Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(inout) :: this character(len=*), intent(in) :: name type( compiler_t ), intent(in) :: compiler type( error_t ), intent(out), allocatable :: error generic, public :: resolve => resolve_cmd, resolve_model, resolve_package_config private subroutine resolve_cmd(self, settings, error) Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(in) :: self class( fpm_cmd_settings ), intent(inout) :: settings type( error_t ), intent(out), allocatable :: error private subroutine resolve_model(self, model, error) Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(in) :: self type( fpm_model_t ), intent(inout) :: model type( error_t ), intent(out), allocatable :: error private subroutine resolve_package_config(self, package, error) Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(in) :: self type( package_config_t ), intent(inout) :: package type( error_t ), intent(out), allocatable :: error Source Code type , public :: metapackage_t !> Package version (if supported) type ( version_t ), allocatable :: version logical :: has_link_libraries = . false . logical :: has_link_flags = . false . logical :: has_build_flags = . false . logical :: has_fortran_flags = . false . logical :: has_c_flags = . false . logical :: has_cxx_flags = . false . logical :: has_include_dirs = . false . logical :: has_dependencies = . false . logical :: has_run_command = . false . logical :: has_external_modules = . false . !> List of compiler flags and options to be added type ( string_t ) :: flags type ( string_t ) :: fflags type ( string_t ) :: cflags type ( string_t ) :: cxxflags type ( string_t ) :: link_flags type ( string_t ) :: run_command type ( string_t ), allocatable :: incl_dirs (:) type ( string_t ), allocatable :: link_libs (:) type ( string_t ), allocatable :: external_modules (:) !> Special fortran features type ( fortran_features_t ), allocatable :: fortran !> List of Development dependency meta data. !> Metapackage dependencies are never exported from the model type ( dependency_config_t ), allocatable :: dependency (:) contains !> Clean metapackage structure procedure :: destroy !> Initialize the metapackage structure from its given name procedure :: new => init_from_name !> Add metapackage dependencies to the model procedure , private :: resolve_cmd procedure , private :: resolve_model procedure , private :: resolve_package_config generic :: resolve => resolve_cmd , resolve_model , resolve_package_config end type metapackage_t","tags":"","loc":"type/metapackage_t.html"},{"title":"enum_descriptor – Fortran-lang/fpm ","text":"type, public :: enum_descriptor Possible git target Components Type Visibility Attributes Name Initial integer, public :: branch = 201 Branch in git repository integer, public :: default = 200 Default target integer, public :: error = -999 Invalid descriptor integer, public :: revision = 203 Commit hash integer, public :: tag = 202 Tag in git repository Source Code type :: enum_descriptor !> Default target integer :: default = 200 !> Branch in git repository integer :: branch = 201 !> Tag in git repository integer :: tag = 202 !> Commit hash integer :: revision = 203 !> Invalid descriptor integer :: error = - 999 end type enum_descriptor","tags":"","loc":"type/enum_descriptor.html"},{"title":"git_target_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: git_target_t Description of an git target Components Type Visibility Attributes Name Initial integer, public :: descriptor = git_descriptor%default Kind of the git target character(len=:), public, allocatable :: object Additional descriptor of the git object character(len=:), public, allocatable :: url Target URL of the git repository Type-Bound Procedures procedure, public :: checkout Fetch and checkout in local directory public subroutine checkout (self, local_path, error) Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target character(len=*), intent(in) :: local_path Local path to checkout in type( error_t ), intent(out), allocatable :: error Error generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml public subroutine dump_to_toml (self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Show information on instance public subroutine info (self, unit, verbosity) Show information on git target Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml public subroutine load_from_toml (self, table, error) Read dependency from toml table (no checks made at this stage) Read more… Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => git_is_same Serialization interface public function git_is_same (this, that) Check that two git targets are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: git_target_t !> Kind of the git target integer :: descriptor = git_descriptor % default !> Target URL of the git repository character ( len = :), allocatable :: url !> Additional descriptor of the git object character ( len = :), allocatable :: object contains !> Fetch and checkout in local directory procedure :: checkout !> Show information on instance procedure :: info !> Serialization interface procedure :: serializable_is_same => git_is_same procedure :: dump_to_toml procedure :: load_from_toml end type git_target_t","tags":"","loc":"type/git_target_t.html"},{"title":"dependency_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: dependency_config_t Configuration meta data for a dependency Components Type Visibility Attributes Name Initial type( git_target_t ), public, allocatable :: git Git descriptor character(len=:), public, allocatable :: name Name of the dependency character(len=:), public, allocatable :: namespace Namespace which the dependency belongs to.\nEnables multiple dependencies with the same name.\nRequired for dependencies that are obtained via the official registry. character(len=:), public, allocatable :: path Local target type( preprocess_config_t ), public, allocatable :: preprocess (:) Requested macros for the dependency type( version_t ), public, allocatable :: requested_version The requested version of the dependency.\nThe latest version is used if not specified. Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(in) :: self Instance of the dependency configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => dependency_is_same Serialization interface private function dependency_is_same(this, that) Check that two dependency configs are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: dependency_config_t !> Name of the dependency character ( len = :), allocatable :: name !> Local target character ( len = :), allocatable :: path !> Namespace which the dependency belongs to. !> Enables multiple dependencies with the same name. !> Required for dependencies that are obtained via the official registry. character ( len = :), allocatable :: namespace !> The requested version of the dependency. !> The latest version is used if not specified. type ( version_t ), allocatable :: requested_version !> Requested macros for the dependency type ( preprocess_config_t ), allocatable :: preprocess (:) !> Git descriptor type ( git_target_t ), allocatable :: git contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => dependency_is_same procedure :: dump_to_toml procedure :: load_from_toml end type dependency_config_t","tags":"","loc":"type/dependency_config_t.html"},{"title":"downloader_t – Fortran-lang/fpm ","text":"type, public :: downloader_t This type could be entirely avoided but it is quite practical because it can be mocked for testing. Type-Bound Procedures procedure, public, nopass :: get_file private subroutine get_file(url, tmp_pkg_file, error) Download a file from a url using either curl or wget. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url character(len=*), intent(in) :: tmp_pkg_file type( error_t ), intent(out), allocatable :: error procedure, public, nopass :: get_pkg_data private subroutine get_pkg_data(url, version, tmp_pkg_file, json, error) Perform an http get request, save output to file, and parse json. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url type( version_t ), intent(in), allocatable :: version character(len=*), intent(in) :: tmp_pkg_file type(json_object), intent(out) :: json type( error_t ), intent(out), allocatable :: error procedure, public, nopass :: unpack private subroutine unpack(tmp_pkg_file, destination, error) Unpack a tarball to a destination. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: tmp_pkg_file Path to tarball. character(len=*), intent(in) :: destination Destination to unpack to. type( error_t ), intent(out), allocatable :: error Error handling. procedure, public, nopass :: upload_form private subroutine upload_form(endpoint, form_data, verbose, error) Perform an http post request with form data. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: endpoint Endpoint to upload to. type( string_t ), intent(in) :: form_data (:) Form data to upload. logical, intent(in) :: verbose Print additional information if true. type( error_t ), intent(out), allocatable :: error Error handling.","tags":"","loc":"type/downloader_t.html"},{"title":"dependency_node_t – Fortran-lang/fpm ","text":"type, public, extends( dependency_config_t ) :: dependency_node_t Dependency node in the projects dependency tree Components Type Visibility Attributes Name Initial logical, public :: cached = .false. Dependency was loaded from a cache logical, public :: done = .false. Dependency is handled type( git_target_t ), public, allocatable :: git Git descriptor character(len=:), public, allocatable :: name Name of the dependency character(len=:), public, allocatable :: namespace Namespace which the dependency belongs to.\nEnables multiple dependencies with the same name.\nRequired for dependencies that are obtained via the official registry. character(len=:), public, allocatable :: path Local target type( preprocess_config_t ), public, allocatable :: preprocess (:) Requested macros for the dependency character(len=:), public, allocatable :: proj_dir Installation prefix of this dependencies type( version_t ), public, allocatable :: requested_version The requested version of the dependency.\nThe latest version is used if not specified. character(len=:), public, allocatable :: revision Checked out revision of the version control system logical, public :: update = .false. Dependency should be updated type( version_t ), public, allocatable :: version Actual version of this dependency Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => node_dump_to_toml private subroutine node_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: get_from_registry Get dependency from the registry. private subroutine get_from_registry(self, target_dir, global_settings, error, downloader_) Get a dependency from the registry. Whether the dependency is fetched\nfrom a local, a custom remote or the official registry is determined\nby the global configuration settings. Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(in) :: self Instance of the dependency configuration. character(len=:), intent(out), allocatable :: target_dir The target directory of the dependency. type( fpm_global_settings ), intent(in) :: global_settings Global configuration settings. type( error_t ), intent(out), allocatable :: error Error handling. class( downloader_t ), intent(in), optional :: downloader_ Downloader instance. procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Call base object info Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(in) :: self Instance of the dependency configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => node_load_from_toml private subroutine node_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: register Update dependency from project manifest. private subroutine register(self, package, root, fetch, revision, error) Update dependency from project manifest Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self Instance of the dependency node type( package_config_t ), intent(in) :: package Package configuration data character(len=*), intent(in) :: root Root directory of the project logical, intent(in) :: fetch Project has been fetched character(len=*), intent(in), optional :: revision Git revision of the project type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: serializable_is_same => dependency_node_is_same Serialization interface private function dependency_node_is_same(this, that) Check that two dependency nodes are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( dependency_config_t ) :: dependency_node_t !> Actual version of this dependency type ( version_t ), allocatable :: version !> Installation prefix of this dependencies character ( len = :), allocatable :: proj_dir !> Checked out revision of the version control system character ( len = :), allocatable :: revision !> Dependency is handled logical :: done = . false . !> Dependency should be updated logical :: update = . false . !> Dependency was loaded from a cache logical :: cached = . false . contains !> Update dependency from project manifest. procedure :: register !> Get dependency from the registry. procedure :: get_from_registry procedure , private :: get_from_local_registry !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => dependency_node_is_same procedure :: dump_to_toml => node_dump_to_toml procedure :: load_from_toml => node_load_from_toml end type dependency_node_t","tags":"","loc":"type/dependency_node_t.html"},{"title":"dependency_tree_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: dependency_tree_t Respresentation of a projects dependencies The dependencies are stored in a simple array for now, this can be replaced\nwith a binary-search tree or a hash table in the future. Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: cache Cache file type( dependency_node_t ), public, allocatable :: dep (:) Flattend list of all dependencies character(len=:), public, allocatable :: dep_dir Installation prefix for dependencies integer, public :: ndep = 0 Number of currently registered dependencies integer, public :: unit = output_unit Unit for IO integer, public :: verbosity = 1 Verbosity of printout Type-Bound Procedures generic, public :: add => add_project, add_project_dependencies, add_dependencies, add_dependency, add_dependency_node Overload procedure to add new dependencies to the tree private subroutine add_project(self, package, error) Add project dependencies, each depth level after each other. We implement this algorithm in an interative rather than a recursive fashion\nas a choice of design. Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( package_config_t ), intent(in) :: package Project configuration to add type( error_t ), intent(out), allocatable :: error Error handling private recursive subroutine add_project_dependencies(self, package, root, main, error) Add a project and its dependencies to the dependency tree\nEnsure allocation fits Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( package_config_t ), intent(in) :: package Project configuration to add character(len=*), intent(in) :: root Current project root directory logical, intent(in) :: main Is the main project type( error_t ), intent(out), allocatable :: error Error handling private subroutine add_dependencies(self, dependency, error) Add a list of dependencies to the dependency tree\nEnsure allocation fits ndep Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( dependency_config_t ), intent(in) :: dependency (:) Dependency configuration to add type( error_t ), intent(out), allocatable :: error Error handling private subroutine add_dependency(self, dependency, error) Add a single dependency to the dependency tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( dependency_config_t ), intent(in) :: dependency Dependency configuration to add type( error_t ), intent(out), allocatable :: error Error handling private subroutine add_dependency_node(self, dependency, error) Add a single dependency node to the dependency tree\nDependency nodes contain additional information (version, git, revision)\nSafety: reallocate if necessary Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( dependency_node_t ), intent(in) :: dependency Dependency configuration to add type( error_t ), intent(out), allocatable :: error Error handling generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? generic, public :: dump_cache => dump_cache_to_file, dump_cache_to_unit, dump_cache_to_toml Writing of dependency tree private subroutine dump_cache_to_file(self, file, error) Write dependency tree to file Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_cache_to_unit(self, unit, error) Write dependency tree to file Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_cache_to_toml(self, table, error) Write dependency tree to TOML datastructure Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: dump_to_toml => tree_dump_to_toml private subroutine tree_dump_to_toml(self, table, error) Dump dependency to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: find => find_name Find a dependency in the tree private pure function find_name(self, name) result(pos) Find a dependency in the dependency tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(in) :: self Instance of the dependency tree character(len=*), intent(in) :: name Dependency configuration to add Return Value integer Index of the dependency procedure, public :: finished Depedendncy resolution finished private pure function finished(self) Check if we are done with the dependency resolution Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(in) :: self Instance of the dependency tree Return Value logical All dependencies are updated generic, public :: has => has_dependency True if entity can be found private pure function has_dependency(self, dependency) True if dependency is part of the tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(in) :: self Instance of the dependency tree class( dependency_node_t ), intent(in) :: dependency Dependency configuration to check Return Value logical generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format generic, public :: load_cache => load_cache_from_file, load_cache_from_unit, load_cache_from_toml Reading of dependency tree private subroutine load_cache_from_file(self, file, error) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_cache_from_unit(self, unit, error) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_cache_from_toml(self, table, error) Read dependency tree from TOML data structure Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: load_from_toml => tree_load_from_toml private subroutine tree_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical generic, public :: resolve => resolve_dependencies, resolve_dependency Resolve dependencies private subroutine resolve_dependencies(self, root, error) Resolve all dependencies in the tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: root Current installation prefix type( error_t ), intent(out), allocatable :: error Error handling private subroutine resolve_dependency(self, dependency, global_settings, root, error) Resolve a single dependency node Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( dependency_node_t ), intent(inout) :: dependency Dependency configuration to add type( fpm_global_settings ), intent(in) :: global_settings Global configuration settings. character(len=*), intent(in) :: root Current installation prefix type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: serializable_is_same => dependency_tree_is_same Serialization interface private function dependency_tree_is_same(this, that) Check that two dependency trees are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error generic, public :: update => update_dependency, update_tree Update dependency tree private subroutine update_dependency(self, name, error) Update dependency tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: name Name of the dependency to update type( error_t ), intent(out), allocatable :: error Error handling private subroutine update_tree(self, error) Update whole dependency tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( error_t ), intent(out), allocatable :: error Error handling Source Code type , extends ( serializable_t ) :: dependency_tree_t !> Unit for IO integer :: unit = output_unit !> Verbosity of printout integer :: verbosity = 1 !> Installation prefix for dependencies character ( len = :), allocatable :: dep_dir !> Number of currently registered dependencies integer :: ndep = 0 !> Flattend list of all dependencies type ( dependency_node_t ), allocatable :: dep (:) !> Cache file character ( len = :), allocatable :: cache contains !> Overload procedure to add new dependencies to the tree generic :: add => add_project , add_project_dependencies , add_dependencies , & add_dependency , add_dependency_node !> Main entry point to add a project procedure , private :: add_project !> Add a project and its dependencies to the dependency tree procedure , private :: add_project_dependencies !> Add a list of dependencies to the dependency tree procedure , private :: add_dependencies !> Add a single dependency to the dependency tree procedure , private :: add_dependency !> Add a single dependency node to the dependency tree procedure , private :: add_dependency_node !> Resolve dependencies generic :: resolve => resolve_dependencies , resolve_dependency !> Resolve dependencies procedure , private :: resolve_dependencies !> Resolve dependency procedure , private :: resolve_dependency !> True if entity can be found generic :: has => has_dependency !> True if dependency is part of the tree procedure , private :: has_dependency !> Find a dependency in the tree generic :: find => find_name !> Find a dependency by its name procedure , private :: find_name !> Depedendncy resolution finished procedure :: finished !> Reading of dependency tree generic :: load_cache => load_cache_from_file , load_cache_from_unit , load_cache_from_toml !> Read dependency tree from file procedure , private :: load_cache_from_file !> Read dependency tree from formatted unit procedure , private :: load_cache_from_unit !> Read dependency tree from TOML data structure procedure , private :: load_cache_from_toml !> Writing of dependency tree generic :: dump_cache => dump_cache_to_file , dump_cache_to_unit , dump_cache_to_toml !> Write dependency tree to file procedure , private :: dump_cache_to_file !> Write dependency tree to formatted unit procedure , private :: dump_cache_to_unit !> Write dependency tree to TOML data structure procedure , private :: dump_cache_to_toml !> Update dependency tree generic :: update => update_dependency , update_tree !> Update a list of dependencies procedure , private :: update_dependency !> Update all dependencies in the tree procedure , private :: update_tree !> Serialization interface procedure :: serializable_is_same => dependency_tree_is_same procedure :: dump_to_toml => tree_dump_to_toml procedure :: load_from_toml => tree_load_from_toml end type dependency_tree_t","tags":"","loc":"type/dependency_tree_t.html"},{"title":"preprocess_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: preprocess_config_t Configuration meta data for a preprocessor Components Type Visibility Attributes Name Initial type( string_t ), public, allocatable :: directories (:) Directories to search for files to be preprocessed type( string_t ), public, allocatable :: macros (:) Macros to be defined for the preprocessor character(len=:), public, allocatable :: name Name of the preprocessor type( string_t ), public, allocatable :: suffixes (:) Suffixes of the files to be preprocessed Type-Bound Procedures procedure, public :: add_config private subroutine add_config(this, that) Add preprocessor settings Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(inout) :: this type( preprocess_config_t ), intent(in) :: that procedure, public :: destroy Operations private elemental subroutine destroy(this) Clean preprocessor structure Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(inout) :: this generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on this instance Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(in) :: self Instance of the preprocess configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout procedure, public :: is_cpp Properties private function is_cpp(this) Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(in) :: this Return Value logical procedure, public :: is_fypp private function is_fypp(this) Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(in) :: this Return Value logical generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => preprocess_is_same Serialization interface private function preprocess_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: preprocess_config_t !> Name of the preprocessor character ( len = :), allocatable :: name !> Suffixes of the files to be preprocessed type ( string_t ), allocatable :: suffixes (:) !> Directories to search for files to be preprocessed type ( string_t ), allocatable :: directories (:) !> Macros to be defined for the preprocessor type ( string_t ), allocatable :: macros (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => preprocess_is_same procedure :: dump_to_toml procedure :: load_from_toml !> Operations procedure :: destroy procedure :: add_config !> Properties procedure :: is_cpp procedure :: is_fypp end type preprocess_config_t","tags":"","loc":"type/preprocess_config_t.html"},{"title":"fpm_global_settings – Fortran-lang/fpm ","text":"type, public :: fpm_global_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: config_file_name Name of the global config file. The default is config.toml . character(len=:), public, allocatable :: path_to_config_folder Path to the global config file excluding the file name. type(fpm_registry_settings), public, allocatable :: registry_settings Registry configs. Type-Bound Procedures procedure, public :: full_path private function full_path(self) result(result) The full path to the global config file. Arguments Type Intent Optional Attributes Name class( fpm_global_settings ), intent(in) :: self Return Value character(len=:), allocatable procedure, public :: has_custom_location private elemental function has_custom_location(self) True if the global config file is not at the default location. Arguments Type Intent Optional Attributes Name class( fpm_global_settings ), intent(in) :: self Return Value logical procedure, public :: path_to_config_folder_or_empty private pure function path_to_config_folder_or_empty(self) The path to the global config directory. Arguments Type Intent Optional Attributes Name class( fpm_global_settings ), intent(in) :: self Return Value character(len=:), allocatable","tags":"","loc":"type/fpm_global_settings.html"},{"title":"fortran_features_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: fortran_features_t Enabled Fortran language features Components Type Visibility Attributes Name Initial logical, public :: implicit_external = .false. Use implicit external interface logical, public :: implicit_typing = .false. Use default implicit typing character(len=:), public, allocatable :: source_form Form to use for all Fortran sources Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => fft_dump_to_toml private subroutine fft_dump_to_toml(self, table, error) Dump fortran features to toml table Arguments Type Intent Optional Attributes Name class( fortran_features_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => fft_load_from_toml private subroutine fft_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( fortran_features_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => fft_is_same Serialization interface private function fft_is_same(this, that) Check that two fortran feature objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( fortran_features_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: fortran_features_t !> Use default implicit typing logical :: implicit_typing = . false . !> Use implicit external interface logical :: implicit_external = . false . !> Form to use for all Fortran sources character (:), allocatable :: source_form contains !> Serialization interface procedure :: serializable_is_same => fft_is_same procedure :: dump_to_toml => fft_dump_to_toml procedure :: load_from_toml => fft_load_from_toml end type fortran_features_t","tags":"","loc":"type/fortran_features_t.html"},{"title":"fpm_model_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: fpm_model_t Type describing everything required to build\n the root package and its dependencies. Components Type Visibility Attributes Name Initial type( archiver_t ), public :: archiver Archiver object character(len=:), public, allocatable :: build_prefix Base directory for build character(len=:), public, allocatable :: c_compile_flags Command line flags passed to C for compilation type( compiler_t ), public :: compiler Compiler object character(len=:), public, allocatable :: cxx_compile_flags Command line flags passed to C++ for compilation type( dependency_tree_t ), public :: deps Project dependencies logical, public :: enforce_module_names = .false. Whether module names should be prefixed with the package name type( string_t ), public, allocatable :: external_modules (:) External modules used character(len=:), public, allocatable :: fortran_compile_flags Command line flags passed to fortran for compilation type( string_t ), public, allocatable :: include_dirs (:) Include directories logical, public :: include_tests = .true. Whether tests should be added to the build list character(len=:), public, allocatable :: link_flags Command line flags passed to the linker type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public :: module_prefix Prefix for all module names character(len=:), public, allocatable :: package_name Name of root package type( package_t ), public, allocatable :: packages (:) Array of packages (including the root package) Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => model_dump_to_toml private subroutine model_dump_to_toml(self, table, error) Dump dependency to toml table Array of packages (including the root package) Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( fpm_model_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => model_load_from_toml private subroutine model_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Read all packages Arguments Type Intent Optional Attributes Name class( fpm_model_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => model_is_same Serialization interface private function model_is_same(this, that) Check that two model objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( fpm_model_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: fpm_model_t !> Name of root package character (:), allocatable :: package_name !> Array of packages (including the root package) type ( package_t ), allocatable :: packages (:) !> Compiler object type ( compiler_t ) :: compiler !> Archiver object type ( archiver_t ) :: archiver !> Command line flags passed to fortran for compilation character (:), allocatable :: fortran_compile_flags !> Command line flags passed to C for compilation character (:), allocatable :: c_compile_flags !> Command line flags passed to C++ for compilation character (:), allocatable :: cxx_compile_flags !> Command line flags passed to the linker character (:), allocatable :: link_flags !> Base directory for build character (:), allocatable :: build_prefix !> Include directories type ( string_t ), allocatable :: include_dirs (:) !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> External modules used type ( string_t ), allocatable :: external_modules (:) !> Project dependencies type ( dependency_tree_t ) :: deps !> Whether tests should be added to the build list logical :: include_tests = . true . !> Whether module names should be prefixed with the package name logical :: enforce_module_names = . false . !> Prefix for all module names type ( string_t ) :: module_prefix contains !> Serialization interface procedure :: serializable_is_same => model_is_same procedure :: dump_to_toml => model_dump_to_toml procedure :: load_from_toml => model_load_from_toml end type fpm_model_t","tags":"","loc":"type/fpm_model_t.html"},{"title":"package_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: package_t Type for describing a single package Components Type Visibility Attributes Name Initial logical, public :: enforce_module_names = .false. Module naming conventions type( fortran_features_t ), public :: features Language features type( string_t ), public :: module_prefix Prefix for all module names character(len=:), public, allocatable :: name Name of package type( preprocess_config_t ), public :: preprocess List of macros. type( srcfile_t ), public, allocatable :: sources (:) Array of sources character(len=:), public, allocatable :: version Package version number. Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => package_dump_to_toml private subroutine package_dump_to_toml(self, table, error) Dump dependency to toml table Create a preprocessor table\nCreate a fortran table\nCreate a sources table Arguments Type Intent Optional Attributes Name class( package_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => package_load_from_toml private subroutine package_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( package_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => package_is_same Serialization interface private function package_is_same(this, that) Check that two package objects are equal\nModule naming\nFortran features All checks passed! Arguments Type Intent Optional Attributes Name class( package_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: package_t !> Name of package character (:), allocatable :: name !> Array of sources type ( srcfile_t ), allocatable :: sources (:) !> List of macros. type ( preprocess_config_t ) :: preprocess !> Package version number. character (:), allocatable :: version !> Module naming conventions logical :: enforce_module_names = . false . !> Prefix for all module names type ( string_t ) :: module_prefix !> Language features type ( fortran_features_t ) :: features contains !> Serialization interface procedure :: serializable_is_same => package_is_same procedure :: dump_to_toml => package_dump_to_toml procedure :: load_from_toml => package_load_from_toml end type package_t","tags":"","loc":"type/package_t.html"},{"title":"srcfile_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: srcfile_t Type for describing a source file Components Type Visibility Attributes Name Initial integer(kind=int64), public :: digest Current hash character(len=:), public, allocatable :: exe_name Name of executable for FPM_UNIT_PROGRAM character(len=:), public, allocatable :: file_name File path relative to cwd type( string_t ), public, allocatable :: include_dependencies (:) Files INCLUDEd by this source file type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public, allocatable :: modules_provided (:) Modules provided by this source file (lowerstring) type( string_t ), public, allocatable :: modules_used (:) Modules USEd by this source file (lowerstring) type( string_t ), public, allocatable :: parent_modules (:) Parent modules (submodules only) integer, public :: unit_scope = FPM_SCOPE_UNKNOWN Target module-use scope integer, public :: unit_type = FPM_UNIT_UNKNOWN Type of source unit Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => srcfile_dump_to_toml private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => srcfile_load_from_toml private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => srcfile_is_same Serialization interface private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: srcfile_t !> File path relative to cwd character (:), allocatable :: file_name !> Name of executable for FPM_UNIT_PROGRAM character (:), allocatable :: exe_name !> Target module-use scope integer :: unit_scope = FPM_SCOPE_UNKNOWN !> Modules provided by this source file (lowerstring) type ( string_t ), allocatable :: modules_provided (:) !> Type of source unit integer :: unit_type = FPM_UNIT_UNKNOWN !> Parent modules (submodules only) type ( string_t ), allocatable :: parent_modules (:) !> Modules USEd by this source file (lowerstring) type ( string_t ), allocatable :: modules_used (:) !> Files INCLUDEd by this source file type ( string_t ), allocatable :: include_dependencies (:) !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> Current hash integer ( int64 ) :: digest contains !> Serialization interface procedure :: serializable_is_same => srcfile_is_same procedure :: dump_to_toml => srcfile_dump_to_toml procedure :: load_from_toml => srcfile_load_from_toml end type srcfile_t","tags":"","loc":"type/srcfile_t.html"},{"title":"library_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: library_config_t Configuration meta data for a library Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: build_script Alternative build script to be invoked type( string_t ), public, allocatable :: include_dir (:) Include path prefix character(len=:), public, allocatable :: source_dir Source path prefix Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Arguments Type Intent Optional Attributes Name class( library_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( library_config_t ), intent(in) :: self Instance of the library configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( library_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => library_is_same Serialization interface private function library_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( library_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: library_config_t !> Source path prefix character ( len = :), allocatable :: source_dir !> Include path prefix type ( string_t ), allocatable :: include_dir (:) !> Alternative build script to be invoked character ( len = :), allocatable :: build_script contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => library_is_same procedure :: dump_to_toml procedure :: load_from_toml end type library_config_t","tags":"","loc":"type/library_config_t.html"},{"title":"error_t – Fortran-lang/fpm ","text":"type, public :: error_t Data type defining an error Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: message Error message Source Code type :: error_t !> Error message character ( len = :), allocatable :: message end type error_t","tags":"","loc":"type/error_t.html"},{"title":"version_t – Fortran-lang/fpm ","text":"type, public :: version_t Type-Bound Procedures generic, public :: operator(.match.) => match Compare a version against a version constraint (x.x.0 <= v < x.x.HUGE) private elemental function match(lhs, rhs) Try to match first version against second version Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical Version match following semantic versioning rules generic, public :: operator(/=) => not_equals private elemental function not_equals(lhs, rhs) result(not_equal) Check two versions for inequality Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical Version mismatch generic, public :: operator(<) => less private elemental function less(lhs, rhs) result(is_less) Relative comparison of two versions Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical First version is less generic, public :: operator(<=) => less_equals private elemental function less_equals(lhs, rhs) result(is_less_equal) Relative comparison of two versions Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical First version is less or equal generic, public :: operator(==) => equals private elemental function equals(lhs, rhs) result(is_equal) Check to version numbers for equality Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical Version match generic, public :: operator(>) => greater private elemental function greater(lhs, rhs) result(is_greater) Relative comparison of two versions Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical First version is greater generic, public :: operator(>=) => greater_equals private elemental function greater_equals(lhs, rhs) result(is_greater_equal) Relative comparison of two versions Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical First version is greater or equal procedure, public :: s Create a printable string from a version data type private pure function s(self) result(string) Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: self Version number Return Value character(len=:), allocatable Character representation of the version Source Code type :: version_t private !> Version numbers found integer , allocatable :: num (:) contains generic :: operator ( == ) => equals procedure , private :: equals generic :: operator ( /= ) => not_equals procedure , private :: not_equals generic :: operator ( > ) => greater procedure , private :: greater generic :: operator ( < ) => less procedure , private :: less generic :: operator ( >= ) => greater_equals procedure , private :: greater_equals generic :: operator ( <= ) => less_equals procedure , private :: less_equals !> Compare a version against a version constraint (x.x.0 <= v < x.x.HUGE) generic :: operator (. match .) => match procedure , private :: match !> Create a printable string from a version data type procedure :: s end type version_t","tags":"","loc":"type/version_t.html"},{"title":"executable_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: executable_config_t Configuation meta data for an executable Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(in) :: self Instance of the executable configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => exe_is_same Serialization interface private function exe_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: executable_config_t !> Name of the resulting executable character ( len = :), allocatable :: name !> Source directory for collecting the executable character ( len = :), allocatable :: source_dir !> Name of the source file declaring the main program character ( len = :), allocatable :: main !> Dependency meta data for this executable type ( dependency_config_t ), allocatable :: dependency (:) !> Libraries to link against type ( string_t ), allocatable :: link (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => exe_is_same procedure :: dump_to_toml procedure :: load_from_toml end type executable_config_t","tags":"","loc":"type/executable_config_t.html"},{"title":"example_config_t – Fortran-lang/fpm ","text":"type, public, extends( executable_config_t ) :: example_config_t Configuation meta data for an example Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( example_config_t ), intent(in) :: self Instance of the example configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => exe_is_same Serialization interface private function exe_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( executable_config_t ) :: example_config_t contains !> Print information on this instance procedure :: info end type example_config_t","tags":"","loc":"type/example_config_t.html"},{"title":"archiver_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: archiver_t Definition of archiver object Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: ar Path to archiver logical, public :: echo = .true. Print all command logical, public :: use_response_file = .false. Use response files to pass arguments logical, public :: verbose = .true. Verbose output of command Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml public subroutine dump_to_toml (self, table, error) Dump dependency to toml table Read more… Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml public subroutine load_from_toml (self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: make_archive Create static archive public subroutine make_archive (self, output, args, log_file, stat) Create an archive Read more… Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: self Instance of the archiver object character(len=*), intent(in) :: output Name of the archive to generate type( string_t ), intent(in) :: args (:) Object files to include into the archive character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => ar_is_same Serialization interface public function ar_is_same (this, that) Check that two archiver_t objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: archiver_t !> Path to archiver character ( len = :), allocatable :: ar !> Use response files to pass arguments logical :: use_response_file = . false . !> Print all command logical :: echo = . true . !> Verbose output of command logical :: verbose = . true . contains !> Create static archive procedure :: make_archive !> Serialization interface procedure :: serializable_is_same => ar_is_same procedure :: dump_to_toml procedure :: load_from_toml end type archiver_t","tags":"","loc":"type/archiver_t.html"},{"title":"compiler_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: compiler_t Definition of compiler object Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: cc Path to the C compiler character(len=:), public, allocatable :: cxx Path to the C++ compiler logical, public :: echo = .true. Print all commands character(len=:), public, allocatable :: fc Path to the Fortran compiler integer(kind=compiler_enum), public :: id = id_unknown Identifier of the compiler logical, public :: verbose = .true. Verbose output of command Type-Bound Procedures procedure, public :: check_fortran_source_runs Fortran feature support public function check_fortran_source_runs (self, input) result(success) Run a single-source Fortran program using the current compiler\nCompile a Fortran object\nCreate temporary source file\nWrite contents\nCompile and link program\nRun and retrieve exit code Read more… Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Program Source Return Value logical procedure, public :: compile_c Compile a C object public subroutine compile_c (self, input, output, args, log_file, stat) Compile a C object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag procedure, public :: compile_cpp Compile a CPP object public subroutine compile_cpp (self, input, output, args, log_file, stat) Compile a CPP object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag procedure, public :: compile_fortran Compile a Fortran object public subroutine compile_fortran (self, input, output, args, log_file, stat) Compile a Fortran object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => compiler_dump public subroutine compiler_dump (self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: enumerate_libraries Enumerate libraries, based on compiler and platform public function enumerate_libraries (self, prefix, libs) result(r) Enumerate libraries, based on compiler and platform Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: prefix type( string_t ), intent(in) :: libs (:) Return Value character(len=:), allocatable procedure, public :: get_default_flags Get default compiler flags public function get_default_flags (self, release) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self logical, intent(in) :: release Return Value character(len=:), allocatable procedure, public :: get_feature_flag Get feature flag public function get_feature_flag (self, feature) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: feature Return Value character(len=:), allocatable procedure, public :: get_include_flag Get flag for include directories public function get_include_flag (self, path) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable procedure, public :: get_main_flags Get flags for the main linking command public subroutine get_main_flags (self, language, flags) Get special flags for the main linker Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: language character(len=:), intent(out), allocatable :: flags procedure, public :: get_module_flag Get flag for module output directories public function get_module_flag (self, path) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable procedure, public :: is_gnu Check whether this is a GNU compiler public pure function is_gnu (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical procedure, public :: is_intel Check whether this is an Intel compiler public pure function is_intel (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical procedure, public :: is_unknown Check whether compiler is recognized public pure function is_unknown (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical procedure, public :: link Link executable public subroutine link (self, output, args, log_file, stat) Link an executable Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => compiler_load public subroutine compiler_load (self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: name => compiler_name Return compiler name public pure function compiler_name (self) result(name) Return a compiler name string Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => compiler_is_same Serialization interface public function compiler_is_same (this, that) Check that two compiler_t objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error procedure, public :: with_qp public function with_qp (self) Check if the current compiler supports 128-bit real precision Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical procedure, public :: with_xdp public function with_xdp (self) Check if the current compiler supports 80-bit “extended” real precision Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical Source Code type , extends ( serializable_t ) :: compiler_t !> Identifier of the compiler integer ( compiler_enum ) :: id = id_unknown !> Path to the Fortran compiler character ( len = :), allocatable :: fc !> Path to the C compiler character ( len = :), allocatable :: cc !> Path to the C++ compiler character ( len = :), allocatable :: cxx !> Print all commands logical :: echo = . true . !> Verbose output of command logical :: verbose = . true . contains !> Get default compiler flags procedure :: get_default_flags !> Get flag for module output directories procedure :: get_module_flag !> Get flag for include directories procedure :: get_include_flag !> Get feature flag procedure :: get_feature_flag !> Get flags for the main linking command procedure :: get_main_flags !> Compile a Fortran object procedure :: compile_fortran !> Compile a C object procedure :: compile_c !> Compile a CPP object procedure :: compile_cpp !> Link executable procedure :: link !> Check whether compiler is recognized procedure :: is_unknown !> Check whether this is an Intel compiler procedure :: is_intel !> Check whether this is a GNU compiler procedure :: is_gnu !> Enumerate libraries, based on compiler and platform procedure :: enumerate_libraries !> Serialization interface procedure :: serializable_is_same => compiler_is_same procedure :: dump_to_toml => compiler_dump procedure :: load_from_toml => compiler_load !> Fortran feature support procedure :: check_fortran_source_runs procedure :: with_xdp procedure :: with_qp !> Return compiler name procedure :: name => compiler_name end type compiler_t","tags":"","loc":"type/compiler_t.html"},{"title":"fpm_build_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_cmd_settings ) :: fpm_build_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_build_settings.html"},{"title":"fpm_clean_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_cmd_settings ) :: fpm_clean_settings Components Type Visibility Attributes Name Initial logical, public :: clean_all = .false. logical, public :: clean_skip = .false. logical, public :: registry_cache = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_clean_settings.html"},{"title":"fpm_cmd_settings – Fortran-lang/fpm ","text":"type, public, abstract :: fpm_cmd_settings Components Type Visibility Attributes Name Initial logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_cmd_settings.html"},{"title":"fpm_export_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_build_settings ) :: fpm_export_settings Settings for exporting model data Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: dump_dependencies character(len=:), public, allocatable :: dump_manifest character(len=:), public, allocatable :: dump_model character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_export_settings.html"},{"title":"fpm_install_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_build_settings ) :: fpm_install_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: bindir logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: includedir character(len=:), public, allocatable :: ldflag character(len=:), public, allocatable :: libdir logical, public :: list = .false. logical, public :: no_rebuild character(len=:), public, allocatable :: prefix character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_install_settings.html"},{"title":"fpm_new_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_cmd_settings ) :: fpm_new_settings Components Type Visibility Attributes Name Initial logical, public :: backfill = .true. character(len=:), public, allocatable :: name logical, public :: verbose = .true. logical, public :: with_bare = .false. logical, public :: with_example = .false. logical, public :: with_executable = .false. logical, public :: with_full = .false. logical, public :: with_lib = .true. logical, public :: with_test = .false. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_new_settings.html"},{"title":"fpm_publish_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_build_settings ) :: fpm_publish_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag logical, public :: is_dry_run = .false. character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: show_package_version = .false. logical, public :: show_upload_data = .false. character(len=:), public, allocatable :: token logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_publish_settings.html"},{"title":"fpm_run_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_build_settings ) :: fpm_run_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: args logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump logical, public :: example character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=ibug), public, allocatable :: name (:) character(len=:), public, allocatable :: profile logical, public :: prune = .true. character(len=:), public, allocatable :: runner character(len=:), public, allocatable :: runner_args logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Type-Bound Procedures procedure, public :: name_ID private function name_ID(cmd, name) Check name in list ID. return 0 if not found\nDefault: not found Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(in) :: cmd character(len=*), intent(in) :: name Return Value integer procedure, public :: runner_command private function runner_command(cmd) result(run_cmd) Build a full runner command (executable + command-line arguments)\nGet executable\nAppend command-line arguments Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(in) :: cmd Return Value character(len=:), allocatable","tags":"","loc":"type/fpm_run_settings.html"},{"title":"fpm_test_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_run_settings ) :: fpm_test_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: args logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump logical, public :: example character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=ibug), public, allocatable :: name (:) character(len=:), public, allocatable :: profile logical, public :: prune = .true. character(len=:), public, allocatable :: runner character(len=:), public, allocatable :: runner_args logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Type-Bound Procedures procedure, public :: name_ID private function name_ID(cmd, name) Check name in list ID. return 0 if not found\nDefault: not found Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(in) :: cmd character(len=*), intent(in) :: name Return Value integer procedure, public :: runner_command private function runner_command(cmd) result(run_cmd) Build a full runner command (executable + command-line arguments)\nGet executable\nAppend command-line arguments Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(in) :: cmd Return Value character(len=:), allocatable","tags":"","loc":"type/fpm_test_settings.html"},{"title":"fpm_update_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_cmd_settings ) :: fpm_update_settings Settings for interacting and updating with project dependencies Components Type Visibility Attributes Name Initial logical, public :: clean character(len=:), public, allocatable :: dump logical, public :: fetch_only character(len=ibug), public, allocatable :: name (:) logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_update_settings.html"},{"title":"metapackage_config_t – Fortran-lang/fpm ","text":"type, public :: metapackage_config_t Configuration data for metapackages Components Type Visibility Attributes Name Initial type( metapackage_request_t ), public :: hdf5 HDF5 type( metapackage_request_t ), public :: minpack fortran-lang minpack type( metapackage_request_t ), public :: mpi Request MPI support type( metapackage_request_t ), public :: openmp Request OpenMP support type( metapackage_request_t ), public :: stdlib Request stdlib support Source Code type :: metapackage_config_t !> Request MPI support type ( metapackage_request_t ) :: mpi !> Request OpenMP support type ( metapackage_request_t ) :: openmp !> Request stdlib support type ( metapackage_request_t ) :: stdlib !> fortran-lang minpack type ( metapackage_request_t ) :: minpack !> HDF5 type ( metapackage_request_t ) :: hdf5 end type metapackage_config_t","tags":"","loc":"type/metapackage_config_t.html"},{"title":"metapackage_request_t – Fortran-lang/fpm ","text":"type, public :: metapackage_request_t Configuration data for a single metapackage request Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: name Metapackage name logical, public :: on = .false. Request flag character(len=:), public, allocatable :: version Version Specification string Source Code type :: metapackage_request_t !> Request flag logical :: on = . false . !> Metapackage name character ( len = :), allocatable :: name !> Version Specification string character ( len = :), allocatable :: version end type metapackage_request_t","tags":"","loc":"type/metapackage_request_t.html"},{"title":"package_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: package_config_t Package meta data Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: author Author meta data type( build_config_t ), public :: build Build configuration data character(len=:), public, allocatable :: copyright Copyright meta data type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data type( dependency_config_t ), public, allocatable :: dev_dependency (:) Development dependency meta data type( example_config_t ), public, allocatable :: example (:) Example meta data type( executable_config_t ), public, allocatable :: executable (:) Executable meta data type( fortran_config_t ), public :: fortran Fortran meta data type( install_config_t ), public :: install Installation configuration data type( library_config_t ), public, allocatable :: library Library meta data character(len=:), public, allocatable :: license License meta data character(len=:), public, allocatable :: maintainer Maintainer meta data type( metapackage_config_t ), public :: meta Metapackage data character(len=:), public, allocatable :: name Name of the package type( preprocess_config_t ), public, allocatable :: preprocess (:) Preprocess meta data type( profile_config_t ), public, allocatable :: profiles (:) Profiles meta data type( test_config_t ), public, allocatable :: test (:) Test meta data type( version_t ), public :: version Package version Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump manifest to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nDuplicate profile names are possible, as multiple profiles are possible with the\nsame name, same compiler, etc. So, use a unique name here\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( package_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( package_config_t ), intent(in) :: self Instance of the package configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read manifest from toml table (no checks made at this stage) Read all packages\nRead all packages\nRead all packages\nRead all packages\nRead all packages\nRead all packages\nRead all packages Arguments Type Intent Optional Attributes Name class( package_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => manifest_is_same Serialization interface private function manifest_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( package_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: package_config_t !> Name of the package character ( len = :), allocatable :: name !> Package version type ( version_t ) :: version !> Build configuration data type ( build_config_t ) :: build !> Metapackage data type ( metapackage_config_t ) :: meta !> Installation configuration data type ( install_config_t ) :: install !> Fortran meta data type ( fortran_config_t ) :: fortran !> License meta data character ( len = :), allocatable :: license !> Author meta data character ( len = :), allocatable :: author !> Maintainer meta data character ( len = :), allocatable :: maintainer !> Copyright meta data character ( len = :), allocatable :: copyright !> Library meta data type ( library_config_t ), allocatable :: library !> Executable meta data type ( executable_config_t ), allocatable :: executable (:) !> Dependency meta data type ( dependency_config_t ), allocatable :: dependency (:) !> Development dependency meta data type ( dependency_config_t ), allocatable :: dev_dependency (:) !> Profiles meta data type ( profile_config_t ), allocatable :: profiles (:) !> Example meta data type ( example_config_t ), allocatable :: example (:) !> Test meta data type ( test_config_t ), allocatable :: test (:) !> Preprocess meta data type ( preprocess_config_t ), allocatable :: preprocess (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => manifest_is_same procedure :: dump_to_toml procedure :: load_from_toml end type package_config_t","tags":"","loc":"type/package_config_t.html"},{"title":"build_progress_t – Fortran-lang/fpm ","text":"type, public :: build_progress_t Build progress object Components Type Visibility Attributes Name Initial type( console_t ), public :: console Console object for updating console lines integer, public :: n_complete Number of completed targets integer, public :: n_target Total number of targets scheduled integer, public, allocatable :: output_lines (:) Store needed when updating previous console lines logical, public :: plain_mode = .true. ‘Plain’ output (no colors or updating) type( build_target_ptr ), public, pointer :: target_queue (:) Queue of scheduled build targets Constructor public interface build_progress_t Constructor for build_progress_t private function new_build_progress(target_queue, plain_mode) result(progress) Initialise a new build progress object Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in), target :: target_queue (:) The queue of scheduled targets logical, intent(in), optional :: plain_mode Enable ‘plain’ output for progress object Return Value type( build_progress_t ) Progress object to initialise Type-Bound Procedures procedure, public :: compiling_status => output_status_compiling Output ‘compiling’ status for build target private subroutine output_status_compiling(progress, queue_index) Output ‘compiling’ status for build target and overall percentage progress Arguments Type Intent Optional Attributes Name class( build_progress_t ), intent(inout) :: progress Progress object integer, intent(in) :: queue_index Index of build target in the target queue procedure, public :: completed_status => output_status_complete Output ‘complete’ status for build target private subroutine output_status_complete(progress, queue_index, build_stat) Output ‘complete’ status for build target and update overall percentage progress Arguments Type Intent Optional Attributes Name class( build_progress_t ), intent(inout) :: progress Progress object integer, intent(in) :: queue_index Index of build target in the target queue integer, intent(in) :: build_stat Build status flag procedure, public :: success => output_progress_success Output finished status for whole package private subroutine output_progress_success(progress) Output finished status for whole package Arguments Type Intent Optional Attributes Name class( build_progress_t ), intent(inout) :: progress Source Code type build_progress_t !> Console object for updating console lines type ( console_t ) :: console !> Number of completed targets integer :: n_complete !> Total number of targets scheduled integer :: n_target !> 'Plain' output (no colors or updating) logical :: plain_mode = . true . !> Store needed when updating previous console lines integer , allocatable :: output_lines (:) !> Queue of scheduled build targets type ( build_target_ptr ), pointer :: target_queue (:) contains !> Output 'compiling' status for build target procedure :: compiling_status => output_status_compiling !> Output 'complete' status for build target procedure :: completed_status => output_status_complete !> Output finished status for whole package procedure :: success => output_progress_success end type build_progress_t","tags":"","loc":"type/build_progress_t.html"},{"title":"build_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: build_config_t Configuration data for build Components Type Visibility Attributes Name Initial logical, public :: auto_examples = .true. Automatic discovery of examples logical, public :: auto_executables = .true. Automatic discovery of executables logical, public :: auto_tests = .true. Automatic discovery of tests type( string_t ), public, allocatable :: external_modules (:) External modules to use type( string_t ), public, allocatable :: link (:) Libraries to link against logical, public :: module_naming = .false. Enforcing of package module names type( string_t ), public :: module_prefix Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump build config to toml table Arguments Type Intent Optional Attributes Name class( build_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on build configuration instance Arguments Type Intent Optional Attributes Name class( build_config_t ), intent(in) :: self Instance of the build configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read build config from toml table (no checks made at this stage) Module naming: fist, attempt boolean value first\nValue found, but not a boolean. Attempt to read a prefix string Arguments Type Intent Optional Attributes Name class( build_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => build_conf_is_same Serialization interface private function build_conf_is_same(this, that) Check that two dependency trees are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( build_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: build_config_t !> Automatic discovery of executables logical :: auto_executables = . true . !> Automatic discovery of examples logical :: auto_examples = . true . !> Automatic discovery of tests logical :: auto_tests = . true . !> Enforcing of package module names logical :: module_naming = . false . type ( string_t ) :: module_prefix !> Libraries to link against type ( string_t ), allocatable :: link (:) !> External modules to use type ( string_t ), allocatable :: external_modules (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => build_conf_is_same procedure :: dump_to_toml procedure :: load_from_toml end type build_config_t","tags":"","loc":"type/build_config_t.html"},{"title":"test_config_t – Fortran-lang/fpm ","text":"type, public, extends( executable_config_t ) :: test_config_t Configuation meta data for an test Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( test_config_t ), intent(in) :: self Instance of the test configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => exe_is_same Serialization interface private function exe_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( executable_config_t ) :: test_config_t contains !> Print information on this instance procedure :: info end type test_config_t","tags":"","loc":"type/test_config_t.html"},{"title":"default_example – Fortran-lang/fpm","text":"public subroutine default_example(self, name) Populate test in case we find the default example/ directory Arguments Type Intent Optional Attributes Name type( example_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package Source Code subroutine default_example ( self , name ) !> Instance of the executable meta data type ( example_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name // \"-demo\" self % source_dir = \"example\" self % main = \"main.f90\" end subroutine default_example","tags":"","loc":"proc/default_example.html"},{"title":"default_executable – Fortran-lang/fpm","text":"public subroutine default_executable(self, name) Populate executable in case we find the default app directory Arguments Type Intent Optional Attributes Name type( executable_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package Source Code subroutine default_executable ( self , name ) !> Instance of the executable meta data type ( executable_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name self % source_dir = \"app\" self % main = \"main.f90\" end subroutine default_executable","tags":"","loc":"proc/default_executable.html"},{"title":"default_library – Fortran-lang/fpm","text":"public subroutine default_library(self) Populate library in case we find the default src directory Arguments Type Intent Optional Attributes Name type( library_config_t ), intent(out) :: self Instance of the library meta data Source Code subroutine default_library ( self ) !> Instance of the library meta data type ( library_config_t ), intent ( out ) :: self self % source_dir = \"src\" self % include_dir = [ string_t ( \"include\" )] end subroutine default_library","tags":"","loc":"proc/default_library.html"},{"title":"default_test – Fortran-lang/fpm","text":"public subroutine default_test(self, name) Populate test in case we find the default test/ directory Arguments Type Intent Optional Attributes Name type( test_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package Source Code subroutine default_test ( self , name ) !> Instance of the executable meta data type ( test_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name // \"-test\" self % source_dir = \"test\" self % main = \"main.f90\" end subroutine default_test","tags":"","loc":"proc/default_test.html"},{"title":"get_package_data – Fortran-lang/fpm","text":"public subroutine get_package_data(package, file, error, apply_defaults) Obtain package meta data from a configuation file Arguments Type Intent Optional Attributes Name type( package_config_t ), intent(out) :: package Parsed package meta data character(len=*), intent(in) :: file Name of the package configuration file type( error_t ), intent(out), allocatable :: error Error status of the operation logical, intent(in), optional :: apply_defaults Apply package defaults (uses file system operations) Source Code subroutine get_package_data ( package , file , error , apply_defaults ) !> Parsed package meta data type ( package_config_t ), intent ( out ) :: package !> Name of the package configuration file character ( len =* ), intent ( in ) :: file !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error !> Apply package defaults (uses file system operations) logical , intent ( in ), optional :: apply_defaults type ( toml_table ), allocatable :: table character ( len = :), allocatable :: root call read_package_file ( table , file , error ) if ( allocated ( error )) return if (. not . allocated ( table )) then call fatal_error ( error , \"Unclassified error while reading: '\" // file // \"'\" ) return end if call new_package ( package , table , dirname ( file ), error ) if ( allocated ( error )) return if ( present ( apply_defaults )) then if ( apply_defaults ) then root = dirname ( file ) if ( len_trim ( root ) == 0 ) root = \".\" call package_defaults ( package , root , error ) if ( allocated ( error )) return end if end if end subroutine get_package_data","tags":"","loc":"proc/get_package_data.html"},{"title":"new_install_config – Fortran-lang/fpm","text":"public subroutine new_install_config(self, table, error) Create a new installation configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( install_config_t ), intent(out) :: self Instance of the install configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_install_config ( self , table , error ) !> Instance of the install configuration type ( install_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"library\" , self % library , . false .) end subroutine new_install_config","tags":"","loc":"proc/new_install_config.html"},{"title":"FPM_TARGET_NAME – Fortran-lang/fpm","text":"public pure function FPM_TARGET_NAME(type) result(msg) Target type name Arguments Type Intent Optional Attributes Name integer, intent(in) :: type Return Value character(len=:), allocatable Source Code pure function FPM_TARGET_NAME ( type ) result ( msg ) integer , intent ( in ) :: type character (:), allocatable :: msg select case ( type ) case ( FPM_TARGET_ARCHIVE ); msg = 'Archive' case ( FPM_TARGET_CPP_OBJECT ); msg = 'C++ object' case ( FPM_TARGET_C_OBJECT ); msg = 'C Object' case ( FPM_TARGET_EXECUTABLE ); msg = 'Executable' case ( FPM_TARGET_OBJECT ); msg = 'Object' case default ; msg = 'Unknown' end select end function FPM_TARGET_NAME","tags":"","loc":"proc/fpm_target_name.html"},{"title":"add_dependency – Fortran-lang/fpm","text":"public subroutine add_dependency(target, dependency) Add pointer to dependeny in target%dependencies Arguments Type Intent Optional Attributes Name type( build_target_t ), intent(inout) :: target type( build_target_t ), intent(in), target :: dependency Source Code subroutine add_dependency ( target , dependency ) type ( build_target_t ), intent ( inout ) :: target type ( build_target_t ) , intent ( in ), target :: dependency target % dependencies = [ target % dependencies , build_target_ptr ( dependency )] end subroutine add_dependency","tags":"","loc":"proc/add_dependency.html"},{"title":"add_target – Fortran-lang/fpm","text":"public subroutine add_target(targets, package, type, output_name, source, link_libraries, features, preprocess, version) Allocate a new target and append to target list Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout), allocatable :: targets (:) character(len=*), intent(in) :: package integer, intent(in) :: type character(len=*), intent(in) :: output_name type( srcfile_t ), intent(in), optional :: source type( string_t ), intent(in), optional :: link_libraries (:) type( fortran_features_t ), intent(in), optional :: features type( preprocess_config_t ), intent(in), optional :: preprocess character(len=*), intent(in), optional :: version Source Code subroutine add_target ( targets , package , type , output_name , source , link_libraries , & & features , preprocess , version ) type ( build_target_ptr ), allocatable , intent ( inout ) :: targets (:) character ( * ), intent ( in ) :: package integer , intent ( in ) :: type character ( * ), intent ( in ) :: output_name type ( srcfile_t ), intent ( in ), optional :: source type ( string_t ), intent ( in ), optional :: link_libraries (:) type ( fortran_features_t ), intent ( in ), optional :: features type ( preprocess_config_t ), intent ( in ), optional :: preprocess character ( * ), intent ( in ), optional :: version integer :: i type ( build_target_t ), pointer :: new_target if (. not . allocated ( targets )) allocate ( targets ( 0 )) ! Check for duplicate outputs do i = 1 , size ( targets ) if ( targets ( i )% ptr % output_name == output_name ) then write ( * , * ) 'Error while building target list: duplicate output object \"' ,& output_name , '\"' if ( present ( source )) write ( * , * ) ' Source file: \"' , source % file_name , '\"' call fpm_stop ( 1 , ' ' ) end if end do allocate ( new_target ) new_target % target_type = type new_target % output_name = output_name new_target % package_name = package if ( present ( source )) new_target % source = source if ( present ( link_libraries )) new_target % link_libraries = link_libraries if ( present ( features )) new_target % features = features if ( present ( preprocess )) then if ( allocated ( preprocess % macros )) new_target % macros = preprocess % macros endif if ( present ( version )) new_target % version = version allocate ( new_target % dependencies ( 0 )) targets = [ targets , build_target_ptr ( new_target )] end subroutine add_target","tags":"","loc":"proc/add_target.html"},{"title":"filter_executable_targets – Fortran-lang/fpm","text":"public subroutine filter_executable_targets(targets, scope, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) integer, intent(in) :: scope type( string_t ), intent(out), allocatable :: list (:) Source Code subroutine filter_executable_targets ( targets , scope , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) integer , intent ( in ) :: scope type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , n n = 0 call resize ( list ) do i = 1 , size ( targets ) if ( is_executable_target ( targets ( i )% ptr , scope )) then if ( n >= size ( list )) call resize ( list ) n = n + 1 list ( n )% s = targets ( i )% ptr % output_file end if end do call resize ( list , n ) end subroutine filter_executable_targets","tags":"","loc":"proc/filter_executable_targets.html"},{"title":"filter_library_targets – Fortran-lang/fpm","text":"public subroutine filter_library_targets(targets, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) type( string_t ), intent(out), allocatable :: list (:) Source Code subroutine filter_library_targets ( targets , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , n n = 0 call resize ( list ) do i = 1 , size ( targets ) if ( targets ( i )% ptr % target_type == FPM_TARGET_ARCHIVE ) then if ( n >= size ( list )) call resize ( list ) n = n + 1 list ( n )% s = targets ( i )% ptr % output_file end if end do call resize ( list , n ) end subroutine filter_library_targets","tags":"","loc":"proc/filter_library_targets.html"},{"title":"filter_modules – Fortran-lang/fpm","text":"public subroutine filter_modules(targets, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) type( string_t ), intent(out), allocatable :: list (:) Source Code subroutine filter_modules ( targets , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , j , n n = 0 call resize ( list ) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if (. not . allocated ( target % source )) cycle if ( target % source % unit_type == FPM_UNIT_SUBMODULE ) cycle if ( n + size ( target % source % modules_provided ) >= size ( list )) call resize ( list ) do j = 1 , size ( target % source % modules_provided ) n = n + 1 list ( n )% s = join_path ( target % output_dir , & target % source % modules_provided ( j )% s ) end do end associate end do call resize ( list , n ) end subroutine filter_modules","tags":"","loc":"proc/filter_modules.html"},{"title":"resolve_module_dependencies – Fortran-lang/fpm","text":"public subroutine resolve_module_dependencies(targets, external_modules, error) Add dependencies to source-based targets ( FPM_TARGET_OBJECT )\n based on any modules used by the corresponding source file. Source file scoping Source files are assigned a scope of either FPM_SCOPE_LIB , FPM_SCOPE_APP or FPM_SCOPE_TEST . The scope controls which\n modules may be used by the source file: Library sources ( FPM_SCOPE_LIB ) may only use modules\n also with library scope. This includes library modules\n from dependencies. Executable sources ( FPM_SCOPE_APP , FPM_SCOPE_TEST ) may use\n library modules (including dependencies) as well as any modules\n corresponding to source files in the same directory or a\n subdirectory of the executable source file. @note Warning\n If a module used by a source file cannot be resolved to\n a source file in the package of the correct scope, then a fatal error is returned by the procedure and model construction fails. Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout), target :: targets (:) type( string_t ), intent(in) :: external_modules (:) type( error_t ), intent(out), allocatable :: error Source Code subroutine resolve_module_dependencies ( targets , external_modules , error ) type ( build_target_ptr ), intent ( inout ), target :: targets (:) type ( string_t ), intent ( in ) :: external_modules (:) type ( error_t ), allocatable , intent ( out ) :: error type ( build_target_ptr ) :: dep integer :: i , j do i = 1 , size ( targets ) if (. not . allocated ( targets ( i )% ptr % source )) cycle do j = 1 , size ( targets ( i )% ptr % source % modules_used ) if ( targets ( i )% ptr % source % modules_used ( j )% s . in . targets ( i )% ptr % source % modules_provided ) then ! Dependency satisfied in same file, skip cycle end if if ( targets ( i )% ptr % source % modules_used ( j )% s . in . external_modules ) then ! Dependency satisfied in system-installed module cycle end if if ( any ( targets ( i )% ptr % source % unit_scope == & [ FPM_SCOPE_APP , FPM_SCOPE_EXAMPLE , FPM_SCOPE_TEST ])) then dep % ptr => & find_module_dependency ( targets , targets ( i )% ptr % source % modules_used ( j )% s , & include_dir = dirname ( targets ( i )% ptr % source % file_name )) else dep % ptr => & find_module_dependency ( targets , targets ( i )% ptr % source % modules_used ( j )% s ) end if if (. not . associated ( dep % ptr )) then call fatal_error ( error , & 'Unable to find source for module dependency: \"' // & targets ( i )% ptr % source % modules_used ( j )% s // & '\" used by \"' // targets ( i )% ptr % source % file_name // '\"' ) return end if call add_dependency ( targets ( i )% ptr , dep % ptr ) end do end do end subroutine resolve_module_dependencies","tags":"","loc":"proc/resolve_module_dependencies.html"},{"title":"targets_from_sources – Fortran-lang/fpm","text":"public subroutine targets_from_sources(targets, model, prune, error) High-level wrapper to generate build target information Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(out), allocatable :: targets (:) The generated list of build targets type( fpm_model_t ), intent(inout), target :: model The package model from which to construct the target list logical, intent(in) :: prune Enable tree-shaking/pruning of module dependencies type( error_t ), intent(out), allocatable :: error Error structure Source Code subroutine targets_from_sources ( targets , model , prune , error ) !> The generated list of build targets type ( build_target_ptr ), intent ( out ), allocatable :: targets (:) !> The package model from which to construct the target list type ( fpm_model_t ), intent ( inout ), target :: model !> Enable tree-shaking/pruning of module dependencies logical , intent ( in ) :: prune !> Error structure type ( error_t ), intent ( out ), allocatable :: error call build_target_list ( targets , model ) call collect_exe_link_dependencies ( targets ) call resolve_module_dependencies ( targets , model % external_modules , error ) if ( allocated ( error )) return if ( prune ) then call prune_build_targets ( targets , root_package = model % package_name ) end if call resolve_target_linking ( targets , model ) end subroutine targets_from_sources","tags":"","loc":"proc/targets_from_sources.html"},{"title":"file_scope_same – Fortran-lang/fpm","text":"public function file_scope_same(this, that) All checks passed! Type Bound file_scope_flag Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Source Code logical function file_scope_same ( this , that ) class ( file_scope_flag ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that file_scope_same = . false . select type ( other => that ) type is ( file_scope_flag ) if ( allocated ( this % file_name ). neqv . allocated ( other % file_name )) return if ( allocated ( this % file_name )) then if (. not .( this % file_name == other % file_name )) return endif if ( allocated ( this % flags ). neqv . allocated ( other % flags )) return if ( allocated ( this % flags )) then if (. not .( this % flags == other % flags )) return endif class default ! Not the same type return end select !> All checks passed! file_scope_same = . true . end function file_scope_same","tags":"","loc":"proc/file_scope_same.html"},{"title":"get_default_profiles – Fortran-lang/fpm","text":"public function get_default_profiles(error) result(default_profiles) Construct an array of built-in profiles Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Error handling Return Value type( profile_config_t ), allocatable, (:) Source Code function get_default_profiles ( error ) result ( default_profiles ) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( profile_config_t ), allocatable :: default_profiles (:) default_profiles = [ & & new_profile ( 'release' , & & 'caf' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -funroll-loops' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'gfortran' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -funroll-loops -fcoarray=single' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'f95' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'nvfortran' , & & OS_ALL , & & flags = ' -Mbackslash' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifort' , & & OS_ALL , & & flags = ' -fp-model precise -pc64 -align all -error-limit 1 -reentrancy& & threaded -nogen-interfaces -assume byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifort' , & & OS_WINDOWS , & & flags = ' /fp:precise /align:all /error-limit:1 /reentrancy:threaded& & /nogen-interfaces /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifx' , & & OS_ALL , & & flags = ' -fp-model=precise -pc64 -align all -error-limit 1 -reentrancy& & threaded -nogen-interfaces -assume byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /fp:precise /align:all /error-limit:1 /reentrancy:threaded& & /nogen-interfaces /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'nagfor' , & & OS_ALL , & & flags = ' -O4 -coarray=single -PIC' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'lfortran' , & & OS_ALL , & & flags = ' flag_lfortran_opt' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'caf' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -fbacktrace' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'gfortran' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -fbacktrace -fcoarray=single' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'f95' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -Wno-maybe-uninitialized -Wno-uninitialized -fbacktrace' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'nvfortran' , & & OS_ALL , & & flags = ' -Minform=inform -Mbackslash -g -Mbounds -Mchkptr -Mchkstk -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifort' , & & OS_ALL , & & flags = ' -warn all -check all -error-limit 1 -O0 -g -assume byterecl -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifort' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1& & /Od /Z7 /assume:byterecl /traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_ALL , & & flags = ' -warn all -check all -error-limit 1 -O0 -g -assume byterecl -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1 /Od /Z7 /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1 /Od /Z7 /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'lfortran' , & & OS_ALL , & & flags = '' , & & is_built_in = . true .) & &] end function get_default_profiles","tags":"","loc":"proc/get_default_profiles.html"},{"title":"info_profile – Fortran-lang/fpm","text":"public function info_profile(profile) result(s) Print a representation of profile_config_t Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(in) :: profile Profile to be represented Return Value character(len=:), allocatable String representation of given profile Variables Type Visibility Attributes Name Initial integer, public :: i Source Code function info_profile ( profile ) result ( s ) !> Profile to be represented type ( profile_config_t ), intent ( in ) :: profile !> String representation of given profile character (:), allocatable :: s integer :: i s = \"profile_config_t(\" s = s // 'profile_name=\"' // profile % profile_name // '\"' s = s // ', compiler=\"' // profile % compiler // '\"' s = s // \", os_type=\" select case ( profile % os_type ) case ( OS_UNKNOWN ) s = s // \"OS_UNKNOWN\" case ( OS_LINUX ) s = s // \"OS_LINUX\" case ( OS_MACOS ) s = s // \"OS_MACOS\" case ( OS_WINDOWS ) s = s // \"OS_WINDOWS\" case ( OS_CYGWIN ) s = s // \"OS_CYGWIN\" case ( OS_SOLARIS ) s = s // \"OS_SOLARIS\" case ( OS_FREEBSD ) s = s // \"OS_FREEBSD\" case ( OS_OPENBSD ) s = s // \"OS_OPENBSD\" case ( OS_ALL ) s = s // \"OS_ALL\" case default s = s // \"INVALID\" end select if ( allocated ( profile % flags )) s = s // ', flags=\"' // profile % flags // '\"' if ( allocated ( profile % c_flags )) s = s // ', c_flags=\"' // profile % c_flags // '\"' if ( allocated ( profile % cxx_flags )) s = s // ', cxx_flags=\"' // profile % cxx_flags // '\"' if ( allocated ( profile % link_time_flags )) s = s // ', link_time_flags=\"' // profile % link_time_flags // '\"' if ( allocated ( profile % file_scope_flags )) then do i = 1 , size ( profile % file_scope_flags ) s = s // ', flags for ' // profile % file_scope_flags ( i )% file_name // & & ' =\"' // profile % file_scope_flags ( i )% flags // '\"' end do end if s = s // \")\" end function info_profile","tags":"","loc":"proc/info_profile.html"},{"title":"new_profile – Fortran-lang/fpm","text":"public function new_profile(profile_name, compiler, os_type, flags, c_flags, cxx_flags, link_time_flags, file_scope_flags, is_built_in) result(profile) Construct a new profile configuration from a TOML data structure Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: profile_name Name of the profile character(len=*), intent(in) :: compiler Name of the compiler integer, intent(in) :: os_type Type of the OS character(len=*), intent(in), optional :: flags Fortran compiler flags character(len=*), intent(in), optional :: c_flags C compiler flags character(len=*), intent(in), optional :: cxx_flags C++ compiler flags character(len=*), intent(in), optional :: link_time_flags Link time compiler flags type( file_scope_flag ), intent(in), optional :: file_scope_flags (:) File scope flags logical, intent(in), optional :: is_built_in Is this profile one of the built-in ones? Return Value type( profile_config_t ) Source Code function new_profile ( profile_name , compiler , os_type , flags , c_flags , cxx_flags , & link_time_flags , file_scope_flags , is_built_in ) & & result ( profile ) !> Name of the profile character ( len =* ), intent ( in ) :: profile_name !> Name of the compiler character ( len =* ), intent ( in ) :: compiler !> Type of the OS integer , intent ( in ) :: os_type !> Fortran compiler flags character ( len =* ), optional , intent ( in ) :: flags !> C compiler flags character ( len =* ), optional , intent ( in ) :: c_flags !> C++ compiler flags character ( len =* ), optional , intent ( in ) :: cxx_flags !> Link time compiler flags character ( len =* ), optional , intent ( in ) :: link_time_flags !> File scope flags type ( file_scope_flag ), optional , intent ( in ) :: file_scope_flags (:) !> Is this profile one of the built-in ones? logical , optional , intent ( in ) :: is_built_in type ( profile_config_t ) :: profile profile % profile_name = profile_name profile % compiler = compiler profile % os_type = os_type if ( present ( flags )) then profile % flags = flags else profile % flags = \"\" end if if ( present ( c_flags )) then profile % c_flags = c_flags else profile % c_flags = \"\" end if if ( present ( cxx_flags )) then profile % cxx_flags = cxx_flags else profile % cxx_flags = \"\" end if if ( present ( link_time_flags )) then profile % link_time_flags = link_time_flags else profile % link_time_flags = \"\" end if if ( present ( file_scope_flags )) then profile % file_scope_flags = file_scope_flags end if if ( present ( is_built_in )) then profile % is_built_in = is_built_in else profile % is_built_in = . false . end if end function new_profile","tags":"","loc":"proc/new_profile.html"},{"title":"os_type_name – Fortran-lang/fpm","text":"public function os_type_name(os_type) Match lowercase string with name of OS to os_type enum Arguments Type Intent Optional Attributes Name integer, intent(in) :: os_type Enum representing type of OS Return Value character(len=:), allocatable Name of operating system Source Code function os_type_name ( os_type ) !> Name of operating system character ( len = :), allocatable :: os_type_name !> Enum representing type of OS integer , intent ( in ) :: os_type select case ( os_type ) case ( OS_ALL ); os_type_name = \"all\" case default ; os_type_name = lower ( OS_NAME ( os_type )) end select end function os_type_name","tags":"","loc":"proc/os_type_name.html"},{"title":"profile_same – Fortran-lang/fpm","text":"public function profile_same(this, that) All checks passed! Type Bound profile_config_t Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Variables Type Visibility Attributes Name Initial integer, public :: ii Source Code logical function profile_same ( this , that ) class ( profile_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii profile_same = . false . select type ( other => that ) type is ( profile_config_t ) if ( allocated ( this % profile_name ). neqv . allocated ( other % profile_name )) return if ( allocated ( this % profile_name )) then if (. not .( this % profile_name == other % profile_name )) return endif if ( allocated ( this % compiler ). neqv . allocated ( other % compiler )) return if ( allocated ( this % compiler )) then if (. not .( this % compiler == other % compiler )) return endif if ( this % os_type /= other % os_type ) return if ( allocated ( this % flags ). neqv . allocated ( other % flags )) return if ( allocated ( this % flags )) then if (. not .( this % flags == other % flags )) return endif if ( allocated ( this % c_flags ). neqv . allocated ( other % c_flags )) return if ( allocated ( this % c_flags )) then if (. not .( this % c_flags == other % c_flags )) return endif if ( allocated ( this % cxx_flags ). neqv . allocated ( other % cxx_flags )) return if ( allocated ( this % cxx_flags )) then if (. not .( this % cxx_flags == other % cxx_flags )) return endif if ( allocated ( this % link_time_flags ). neqv . allocated ( other % link_time_flags )) return if ( allocated ( this % link_time_flags )) then if (. not .( this % link_time_flags == other % link_time_flags )) return endif if ( allocated ( this % file_scope_flags ). neqv . allocated ( other % file_scope_flags )) return if ( allocated ( this % file_scope_flags )) then if (. not . size ( this % file_scope_flags ) == size ( other % file_scope_flags )) return do ii = 1 , size ( this % file_scope_flags ) print * , 'check ii-th file scope: ' , ii if (. not . this % file_scope_flags ( ii ) == other % file_scope_flags ( ii )) return end do endif if ( this % is_built_in . neqv . other % is_built_in ) return class default ! Not the same type return end select !> All checks passed! profile_same = . true . end function profile_same","tags":"","loc":"proc/profile_same.html"},{"title":"file_scope_dump – Fortran-lang/fpm","text":"public subroutine file_scope_dump(self, table, error) Dump to toml table Type Bound file_scope_flag Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine file_scope_dump ( self , table , error ) !> Instance of the serializable object class ( file_scope_flag ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_string ( table , \"file-name\" , self % file_name , error ) if ( allocated ( error )) return call set_string ( table , \"flags\" , self % flags , error ) if ( allocated ( error )) return end subroutine file_scope_dump","tags":"","loc":"proc/file_scope_dump.html"},{"title":"file_scope_load – Fortran-lang/fpm","text":"public subroutine file_scope_load(self, table, error) Read from toml table (no checks made at this stage) Type Bound file_scope_flag Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine file_scope_load ( self , table , error ) !> Instance of the serializable object class ( file_scope_flag ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"file-name\" , self % file_name ) call get_value ( table , \"flags\" , self % flags ) end subroutine file_scope_load","tags":"","loc":"proc/file_scope_load.html"},{"title":"find_profile – Fortran-lang/fpm","text":"public subroutine find_profile(profiles, profile_name, compiler, os_type, found_matching, chosen_profile) Look for profile with given configuration in array profiles Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(in), allocatable :: profiles (:) Array of profiles character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler Name of compiler integer, intent(in) :: os_type Type of operating system (enum) logical, intent(out) :: found_matching Boolean value containing true if matching profile was found type( profile_config_t ), intent(out) :: chosen_profile Last matching profile in the profiles array Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: curr_compiler integer, public :: curr_os integer, public :: curr_priority character(len=:), public, allocatable :: curr_profile_name integer, public :: i integer, public :: priority Source Code subroutine find_profile ( profiles , profile_name , compiler , os_type , found_matching , chosen_profile ) !> Array of profiles type ( profile_config_t ), allocatable , intent ( in ) :: profiles (:) !> Name of profile character (:), allocatable , intent ( in ) :: profile_name !> Name of compiler character (:), allocatable , intent ( in ) :: compiler !> Type of operating system (enum) integer , intent ( in ) :: os_type !> Boolean value containing true if matching profile was found logical , intent ( out ) :: found_matching !> Last matching profile in the profiles array type ( profile_config_t ), intent ( out ) :: chosen_profile character (:), allocatable :: curr_profile_name character (:), allocatable :: curr_compiler integer :: curr_os integer :: i , priority , curr_priority found_matching = . false . if ( size ( profiles ) < 1 ) return ! Try to find profile with matching OS type do i = 1 , size ( profiles ) curr_profile_name = profiles ( i )% profile_name curr_compiler = profiles ( i )% compiler curr_os = profiles ( i )% os_type if ( curr_profile_name . eq . profile_name ) then if ( curr_compiler . eq . compiler ) then if ( curr_os . eq . os_type ) then chosen_profile = profiles ( i ) found_matching = . true . end if end if end if end do ! Try to find profile with OS type 'all' if (. not . found_matching ) then do i = 1 , size ( profiles ) curr_profile_name = profiles ( i )% profile_name curr_compiler = profiles ( i )% compiler curr_os = profiles ( i )% os_type if ( curr_profile_name . eq . profile_name ) then if ( curr_compiler . eq . compiler ) then if ( curr_os . eq . OS_ALL ) then chosen_profile = profiles ( i ) found_matching = . true . end if end if end if end do end if end subroutine find_profile","tags":"","loc":"proc/find_profile.html"},{"title":"get_flags – Fortran-lang/fpm","text":"public subroutine get_flags(profile_name, compiler_name, os_type, key_list, table, profiles, profindex, os_valid) Look for flags, c-flags, link-time-flags key-val pairs\nand files table in a given table and create new profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler integer, intent(in) :: os_type OS type type(toml_key), intent(in), allocatable :: key_list (:) List of keys in the table type(toml_table), intent(in), pointer :: table Table containing OS tables type( profile_config_t ), intent(inout), allocatable :: profiles (:) List of profiles integer, intent(inout) :: profindex Index in the list of profiles logical, intent(in) :: os_valid Was called with valid operating system Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: c_flags character(len=:), public, allocatable :: cxx_flags character(len=:), public, allocatable :: err_message character(len=:), public, allocatable :: file_flags type(toml_key), public, allocatable :: file_list (:) character(len=:), public, allocatable :: file_name type( file_scope_flag ), public, allocatable :: file_scope_flags (:) type(toml_table), public, pointer :: files character(len=:), public, allocatable :: flags integer, public :: ifile integer, public :: ikey logical, public :: is_valid character(len=:), public, allocatable :: key_name character(len=:), public, allocatable :: link_time_flags integer, public :: stat Source Code subroutine get_flags ( profile_name , compiler_name , os_type , key_list , table , profiles , profindex , os_valid ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> OS type integer , intent ( in ) :: os_type !> List of keys in the table type ( toml_key ), allocatable , intent ( in ) :: key_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ) :: profiles (:) !> Index in the list of profiles integer , intent ( inout ) :: profindex !> Was called with valid operating system logical , intent ( in ) :: os_valid character ( len = :), allocatable :: flags , c_flags , cxx_flags , link_time_flags , key_name , file_name , file_flags , err_message type ( toml_table ), pointer :: files type ( toml_key ), allocatable :: file_list (:) type ( file_scope_flag ), allocatable :: file_scope_flags (:) integer :: ikey , ifile , stat logical :: is_valid call get_value ( table , 'flags' , flags ) call get_value ( table , 'c-flags' , c_flags ) call get_value ( table , 'cxx-flags' , cxx_flags ) call get_value ( table , 'link-time-flags' , link_time_flags ) call get_value ( table , 'files' , files ) if ( associated ( files )) then call files % get_keys ( file_list ) allocate ( file_scope_flags ( size ( file_list ))) do ifile = 1 , size ( file_list ) file_name = file_list ( ifile )% key call get_value ( files , file_name , file_flags ) associate ( cur_file => file_scope_flags ( ifile )) if (. not .( path . eq . \"\" )) file_name = join_path ( path , file_name ) cur_file % file_name = file_name cur_file % flags = file_flags end associate end do end if profiles ( profindex ) = new_profile ( profile_name , compiler_name , os_type , & & flags , c_flags , cxx_flags , link_time_flags , file_scope_flags ) profindex = profindex + 1 end subroutine get_flags","tags":"","loc":"proc/get_flags.html"},{"title":"info – Fortran-lang/fpm","text":"public subroutine info(self, unit, verbosity) Write information on instance Type Bound profile_config_t Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: self Instance of the profile configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: fmt = '(\"#\", 1x, a, t30, a)' integer, public :: pr Source Code subroutine info ( self , unit , verbosity ) !> Instance of the profile configuration class ( profile_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if write ( unit , fmt ) \"Profile\" if ( allocated ( self % profile_name )) then write ( unit , fmt ) \"- profile name\" , self % profile_name end if if ( allocated ( self % compiler )) then write ( unit , fmt ) \"- compiler\" , self % compiler end if write ( unit , fmt ) \"- os\" , os_type_name ( self % os_type ) if ( allocated ( self % flags )) then write ( unit , fmt ) \"- compiler flags\" , self % flags end if end subroutine info","tags":"","loc":"proc/info~2.html"},{"title":"match_os_type – Fortran-lang/fpm","text":"public subroutine match_os_type(os_name, os_type) Match os_type enum to a lowercase string with name of OS Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: os_name Name of operating system integer, intent(out) :: os_type Enum representing type of OS Source Code subroutine match_os_type ( os_name , os_type ) !> Name of operating system character ( len = :), allocatable , intent ( in ) :: os_name !> Enum representing type of OS integer , intent ( out ) :: os_type select case ( os_name ) case ( \"linux\" ); os_type = OS_LINUX case ( \"macos\" ); os_type = OS_MACOS case ( \"windows\" ); os_type = OS_WINDOWS case ( \"cygwin\" ); os_type = OS_CYGWIN case ( \"solaris\" ); os_type = OS_SOLARIS case ( \"freebsd\" ); os_type = OS_FREEBSD case ( \"openbsd\" ); os_type = OS_OPENBSD case ( \"all\" ); os_type = OS_ALL case default ; os_type = OS_UNKNOWN end select end subroutine match_os_type","tags":"","loc":"proc/match_os_type.html"},{"title":"new_profiles – Fortran-lang/fpm","text":"public subroutine new_profiles(profiles, table, error) Construct new profiles array from a TOML data structure Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(out), allocatable :: profiles (:) Instance of the dependency configuration type(toml_table), intent(inout), target :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial type(toml_key), public, allocatable :: comp_list (:) character(len=:), public, allocatable :: compiler_name type( profile_config_t ), public, allocatable :: default_profiles (:) integer, public :: iprof logical, public :: is_valid type(toml_key), public, allocatable :: os_list (:) type(toml_key), public, allocatable :: prof_list (:) type(toml_table), public, pointer :: prof_node character(len=:), public, allocatable :: profile_name integer, public :: profiles_size integer, public :: profindex integer, public :: stat Source Code subroutine new_profiles ( profiles , table , error ) !> Instance of the dependency configuration type ( profile_config_t ), allocatable , intent ( out ) :: profiles (:) !> Instance of the TOML data structure type ( toml_table ), target , intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: prof_node type ( toml_key ), allocatable :: prof_list (:) type ( toml_key ), allocatable :: comp_list (:) type ( toml_key ), allocatable :: os_list (:) character ( len = :), allocatable :: profile_name , compiler_name integer :: profiles_size , iprof , stat , profindex logical :: is_valid type ( profile_config_t ), allocatable :: default_profiles (:) path = '' default_profiles = get_default_profiles ( error ) if ( allocated ( error )) return call table % get_keys ( prof_list ) if ( size ( prof_list ) < 1 ) return profiles_size = 0 do iprof = 1 , size ( prof_list ) profile_name = prof_list ( iprof )% key call validate_compiler_name ( profile_name , is_valid ) if ( is_valid ) then profile_name = \"all\" comp_list = prof_list ( iprof : iprof ) prof_node => table call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles_size = profiles_size ) if ( allocated ( error )) return else call validate_os_name ( profile_name , is_valid ) if ( is_valid ) then os_list = prof_list ( iprof : iprof ) profile_name = 'all' compiler_name = DEFAULT_COMPILER call traverse_oss_for_size ( profile_name , compiler_name , os_list , table , profiles_size , error ) if ( allocated ( error )) return else call get_value ( table , profile_name , prof_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Profile \" // prof_list ( iprof )% key // \" must be a table entry\" ) exit end if call prof_node % get_keys ( comp_list ) call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles_size = profiles_size ) if ( allocated ( error )) return end if end if end do profiles_size = profiles_size + size ( default_profiles ) allocate ( profiles ( profiles_size )) do profindex = 1 , size ( default_profiles ) profiles ( profindex ) = default_profiles ( profindex ) end do do iprof = 1 , size ( prof_list ) profile_name = prof_list ( iprof )% key call validate_compiler_name ( profile_name , is_valid ) if ( is_valid ) then profile_name = \"all\" comp_list = prof_list ( iprof : iprof ) prof_node => table call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles = profiles , profindex = profindex ) if ( allocated ( error )) return else call validate_os_name ( profile_name , is_valid ) if ( is_valid ) then os_list = prof_list ( iprof : iprof ) profile_name = 'all' compiler_name = DEFAULT_COMPILER prof_node => table call traverse_oss ( profile_name , compiler_name , os_list , prof_node , profiles , profindex , error ) if ( allocated ( error )) return else call get_value ( table , profile_name , prof_node , stat = stat ) call prof_node % get_keys ( comp_list ) call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles = profiles , profindex = profindex ) if ( allocated ( error )) return end if end if end do ! Apply profiles with profile name 'all' to matching profiles do iprof = 1 , size ( profiles ) if ( profiles ( iprof )% profile_name . eq . 'all' ) then do profindex = 1 , size ( profiles ) if (. not .( profiles ( profindex )% profile_name . eq . 'all' ) & & . and .( profiles ( profindex )% compiler . eq . profiles ( iprof )% compiler ) & & . and .( profiles ( profindex )% os_type . eq . profiles ( iprof )% os_type )) then profiles ( profindex )% flags = profiles ( profindex )% flags // & & \" \" // profiles ( iprof )% flags profiles ( profindex )% c_flags = profiles ( profindex )% c_flags // & & \" \" // profiles ( iprof )% c_flags profiles ( profindex )% cxx_flags = profiles ( profindex )% cxx_flags // & & \" \" // profiles ( iprof )% cxx_flags profiles ( profindex )% link_time_flags = profiles ( profindex )% link_time_flags // & & \" \" // profiles ( iprof )% link_time_flags end if end do end if end do end subroutine new_profiles","tags":"","loc":"proc/new_profiles.html"},{"title":"profile_dump – Fortran-lang/fpm","text":"public subroutine profile_dump(self, table, error) Dump to toml table Because files need a name, fallback if this has no name Type Bound profile_config_t Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ierr Local variables integer, public :: ii Local variables type(toml_table), public, pointer :: ptr type(toml_table), public, pointer :: ptr_deps character(len=30), public :: unnamed Source Code subroutine profile_dump ( self , table , error ) !> Instance of the serializable object class ( profile_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: ierr , ii type ( toml_table ), pointer :: ptr_deps , ptr character ( len = 30 ) :: unnamed call set_string ( table , \"profile-name\" , self % profile_name , error ) if ( allocated ( error )) return call set_string ( table , \"compiler\" , self % compiler , error ) if ( allocated ( error )) return call set_string ( table , \"os-type\" , os_type_name ( self % os_type ), error , 'profile_config_t' ) if ( allocated ( error )) return call set_string ( table , \"flags\" , self % flags , error ) if ( allocated ( error )) return call set_string ( table , \"c-flags\" , self % c_flags , error ) if ( allocated ( error )) return call set_string ( table , \"cxx-flags\" , self % cxx_flags , error ) if ( allocated ( error )) return call set_string ( table , \"link-time-flags\" , self % link_time_flags , error ) if ( allocated ( error )) return if ( allocated ( self % file_scope_flags )) then ! Create dependency table call add_table ( table , \"file-scope-flags\" , ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , \"profile_config_t cannot create file scope table \" ) return end if do ii = 1 , size ( self % file_scope_flags ) associate ( dep => self % file_scope_flags ( ii )) !> Because files need a name, fallback if this has no name if ( len_trim ( dep % file_name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_deps , trim ( unnamed ), ptr ) else call add_table ( ptr_deps , dep % file_name , ptr ) end if if (. not . associated ( ptr )) then call fatal_error ( error , \"profile_config_t cannot create entry for file \" // dep % file_name ) return end if call dep % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do endif call set_value ( table , \"is-built-in\" , self % is_built_in , error , 'profile_config_t' ) if ( allocated ( error )) return 1 format ( 'UNNAMED_FILE_' , i0 ) end subroutine profile_dump","tags":"","loc":"proc/profile_dump.html"},{"title":"profile_load – Fortran-lang/fpm","text":"public subroutine profile_load(self, table, error) Read from toml table (no checks made at this stage) Read all packages Type Bound profile_config_t Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial type(toml_key), public, allocatable :: dep_keys (:) character(len=:), public, allocatable :: flag Local variables integer, public :: ii integer, public :: jj type(toml_key), public, allocatable :: keys (:) type(toml_table), public, pointer :: ptr type(toml_table), public, pointer :: ptr_dep Source Code subroutine profile_load ( self , table , error ) !> Instance of the serializable object class ( profile_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: flag integer :: ii , jj type ( toml_table ), pointer :: ptr_dep , ptr type ( toml_key ), allocatable :: keys (:), dep_keys (:) call table % get_keys ( keys ) call get_value ( table , \"profile-name\" , self % profile_name ) call get_value ( table , \"compiler\" , self % compiler ) call get_value ( table , \"os-type\" , flag ) call match_os_type ( flag , self % os_type ) call get_value ( table , \"flags\" , self % flags ) call get_value ( table , \"c-flags\" , self % c_flags ) call get_value ( table , \"cxx-flags\" , self % cxx_flags ) call get_value ( table , \"link-time-flags\" , self % link_time_flags ) call get_value ( table , \"is-built-in\" , self % is_built_in , error , 'profile_config_t' ) if ( allocated ( error )) return if ( allocated ( self % file_scope_flags )) deallocate ( self % file_scope_flags ) sub_deps : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"file-scope-flags\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'profile_config_t: error retrieving file_scope_flags table' ) return end if !> Read all packages call ptr % get_keys ( dep_keys ) allocate ( self % file_scope_flags ( size ( dep_keys ))) do jj = 1 , size ( dep_keys ) call get_value ( ptr , dep_keys ( jj ), ptr_dep ) call self % file_scope_flags ( jj )% load_from_toml ( ptr_dep , error ) if ( allocated ( error )) return end do end select end do sub_deps end subroutine profile_load","tags":"","loc":"proc/profile_load.html"},{"title":"traverse_compilers – Fortran-lang/fpm","text":"public subroutine traverse_compilers(profile_name, comp_list, table, error, profiles_size, profiles, profindex) Traverse compiler tables Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile type(toml_key), intent(in), allocatable :: comp_list (:) List of OSs in table with profile name given type(toml_table), intent(in), pointer :: table Table containing compiler tables type( error_t ), intent(out), allocatable :: error Error handling integer, intent(inout), optional :: profiles_size Number of profiles in list of profiles type( profile_config_t ), intent(inout), optional, allocatable :: profiles (:) List of profiles integer, intent(inout), optional :: profindex Index in the list of profiles Variables Type Visibility Attributes Name Initial type(toml_table), public, pointer :: comp_node character(len=:), public, allocatable :: compiler_name integer, public :: icomp logical, public :: is_valid type(toml_key), public, allocatable :: os_list (:) integer, public :: stat Source Code subroutine traverse_compilers ( profile_name , comp_list , table , error , profiles_size , profiles , profindex ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> List of OSs in table with profile name given type ( toml_key ), allocatable , intent ( in ) :: comp_list (:) !> Table containing compiler tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Number of profiles in list of profiles integer , intent ( inout ), optional :: profiles_size !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ), optional :: profiles (:) !> Index in the list of profiles integer , intent ( inout ), optional :: profindex character ( len = :), allocatable :: compiler_name type ( toml_table ), pointer :: comp_node type ( toml_key ), allocatable :: os_list (:) integer :: icomp , stat logical :: is_valid if ( size ( comp_list ) < 1 ) return do icomp = 1 , size ( comp_list ) call validate_compiler_name ( comp_list ( icomp )% key , is_valid ) if ( is_valid ) then compiler_name = comp_list ( icomp )% key call get_value ( table , compiler_name , comp_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Compiler \" // comp_list ( icomp )% key // \" must be a table entry\" ) exit end if call comp_node % get_keys ( os_list ) if ( present ( profiles_size )) then call traverse_oss_for_size ( profile_name , compiler_name , os_list , comp_node , profiles_size , error ) if ( allocated ( error )) return else if (. not .( present ( profiles ). and . present ( profindex ))) then call fatal_error ( error , \"Both profiles and profindex have to be present\" ) return end if call traverse_oss ( profile_name , compiler_name , os_list , comp_node , & & profiles , profindex , error ) if ( allocated ( error )) return end if else call fatal_error ( error , '*traverse_compilers*:Error: Compiler name not specified or invalid.' ) end if end do end subroutine traverse_compilers","tags":"","loc":"proc/traverse_compilers.html"},{"title":"traverse_oss – Fortran-lang/fpm","text":"public subroutine traverse_oss(profile_name, compiler_name, os_list, table, profiles, profindex, error) Traverse operating system tables to obtain profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: os_list (:) List of OSs in table with profile name and compiler name given type(toml_table), intent(in), pointer :: table Table containing OS tables type( profile_config_t ), intent(inout), allocatable :: profiles (:) List of profiles integer, intent(inout) :: profindex Index in the list of profiles type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ios logical, public :: is_key_val logical, public :: is_valid type(toml_key), public, allocatable :: key_list (:) character(len=:), public, allocatable :: l_os_name character(len=:), public, allocatable :: os_name type(toml_table), public, pointer :: os_node integer, public :: os_type integer, public :: stat Source Code subroutine traverse_oss ( profile_name , compiler_name , os_list , table , profiles , profindex , error ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of OSs in table with profile name and compiler name given type ( toml_key ), allocatable , intent ( in ) :: os_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ) :: profiles (:) !> Index in the list of profiles integer , intent ( inout ) :: profindex type ( toml_key ), allocatable :: key_list (:) character ( len = :), allocatable :: os_name , l_os_name type ( toml_table ), pointer :: os_node integer :: ios , stat , os_type logical :: is_valid , is_key_val if ( size ( os_list ) < 1 ) return do ios = 1 , size ( os_list ) os_name = os_list ( ios )% key call validate_os_name ( os_name , is_valid ) if ( is_valid ) then call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"os \" // os_name // \" has to be a table\" ) return end if call os_node % get_keys ( key_list ) call match_os_type ( os_name , os_type ) call get_flags ( profile_name , compiler_name , os_type , key_list , os_node , profiles , profindex , . true .) else ! Not lowercase OS name l_os_name = lower ( os_name ) call validate_os_name ( l_os_name , is_valid ) if ( is_valid ) then call fatal_error ( error , '*traverse_oss*:Error: Name of the operating system must be a lowercase string.' ) end if if ( allocated ( error )) return ! Missing OS name is_key_val = . false . os_name = os_list ( ios )% key call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then is_key_val = . true . end if os_node => table os_type = OS_ALL call get_flags ( profile_name , compiler_name , os_type , os_list , os_node , profiles , profindex , . false .) end if end do end subroutine traverse_oss","tags":"","loc":"proc/traverse_oss.html"},{"title":"traverse_oss_for_size – Fortran-lang/fpm","text":"public subroutine traverse_oss_for_size(profile_name, compiler_name, os_list, table, profiles_size, error) Traverse operating system tables to obtain number of profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: os_list (:) List of OSs in table with profile name and compiler name given type(toml_table), intent(in), pointer :: table Table containing OS tables integer, intent(inout) :: profiles_size Number of profiles in list of profiles type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ios logical, public :: is_key_val logical, public :: is_valid type(toml_key), public, allocatable :: key_list (:) logical, public :: key_val_added character(len=:), public, allocatable :: l_os_name character(len=:), public, allocatable :: os_name type(toml_table), public, pointer :: os_node integer, public :: stat Source Code subroutine traverse_oss_for_size ( profile_name , compiler_name , os_list , table , profiles_size , error ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of OSs in table with profile name and compiler name given type ( toml_key ), allocatable , intent ( in ) :: os_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Number of profiles in list of profiles integer , intent ( inout ) :: profiles_size type ( toml_key ), allocatable :: key_list (:) character ( len = :), allocatable :: os_name , l_os_name type ( toml_table ), pointer :: os_node integer :: ios , stat logical :: is_valid , key_val_added , is_key_val if ( size ( os_list ) < 1 ) return key_val_added = . false . do ios = 1 , size ( os_list ) os_name = os_list ( ios )% key call validate_os_name ( os_name , is_valid ) if ( is_valid ) then call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"os \" // os_name // \" has to be a table\" ) return end if call os_node % get_keys ( key_list ) profiles_size = profiles_size + 1 call validate_profile_table ( profile_name , compiler_name , key_list , os_node , error , . true .) else ! Not lowercase OS name l_os_name = lower ( os_name ) call validate_os_name ( l_os_name , is_valid ) if ( is_valid ) then call fatal_error ( error , '*traverse_oss*:Error: Name of the operating system must be a lowercase string.' ) end if if ( allocated ( error )) return ! Missing OS name is_key_val = . false . os_name = os_list ( ios )% key call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then is_key_val = . true . end if os_node => table if ( is_key_val . and .. not . key_val_added ) then key_val_added = . true . is_key_val = . false . profiles_size = profiles_size + 1 else if (. not . is_key_val ) then profiles_size = profiles_size + 1 end if call validate_profile_table ( profile_name , compiler_name , os_list , os_node , error , . false .) end if end do end subroutine traverse_oss_for_size","tags":"","loc":"proc/traverse_oss_for_size.html"},{"title":"validate_compiler_name – Fortran-lang/fpm","text":"public subroutine validate_compiler_name(compiler_name, is_valid) Check if compiler name is a valid compiler name Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: compiler_name Name of a compiler logical, intent(out) :: is_valid Boolean value of whether compiler_name is valid or not Source Code subroutine validate_compiler_name ( compiler_name , is_valid ) !> Name of a compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> Boolean value of whether compiler_name is valid or not logical , intent ( out ) :: is_valid select case ( compiler_name ) case ( \"gfortran\" , \"ifort\" , \"ifx\" , \"pgfortran\" , \"nvfortran\" , \"flang\" , \"caf\" , & & \"f95\" , \"lfortran\" , \"lfc\" , \"nagfor\" , \"crayftn\" , \"xlf90\" , \"ftn95\" ) is_valid = . true . case default is_valid = . false . end select end subroutine validate_compiler_name","tags":"","loc":"proc/validate_compiler_name.html"},{"title":"validate_os_name – Fortran-lang/fpm","text":"public subroutine validate_os_name(os_name, is_valid) Check if os_name is a valid name of a supported OS Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: os_name Name of an operating system logical, intent(out) :: is_valid Boolean value of whether os_name is valid or not Source Code subroutine validate_os_name ( os_name , is_valid ) !> Name of an operating system character ( len = :), allocatable , intent ( in ) :: os_name !> Boolean value of whether os_name is valid or not logical , intent ( out ) :: is_valid select case ( os_name ) case ( \"linux\" , \"macos\" , \"windows\" , \"cygwin\" , \"solaris\" , \"freebsd\" , & & \"openbsd\" , \"unknown\" ) is_valid = . true . case default is_valid = . false . end select end subroutine validate_os_name","tags":"","loc":"proc/validate_os_name.html"},{"title":"validate_profile_table – Fortran-lang/fpm","text":"public subroutine validate_profile_table(profile_name, compiler_name, key_list, table, error, os_valid) Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: key_list (:) List of keys in the table type(toml_table), intent(in), pointer :: table Table containing OS tables type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in) :: os_valid Was called with valid operating system Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: c_flags character(len=:), public, allocatable :: cxx_flags character(len=:), public, allocatable :: err_message character(len=:), public, allocatable :: file_flags type(toml_key), public, allocatable :: file_list (:) character(len=:), public, allocatable :: file_name type(toml_table), public, pointer :: files character(len=:), public, allocatable :: flags integer, public :: ifile integer, public :: ikey logical, public :: is_valid character(len=:), public, allocatable :: key_name character(len=:), public, allocatable :: link_time_flags integer, public :: stat Source Code subroutine validate_profile_table ( profile_name , compiler_name , key_list , table , error , os_valid ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of keys in the table type ( toml_key ), allocatable , intent ( in ) :: key_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Was called with valid operating system logical , intent ( in ) :: os_valid character ( len = :), allocatable :: flags , c_flags , cxx_flags , link_time_flags , key_name , file_name , file_flags , err_message type ( toml_table ), pointer :: files type ( toml_key ), allocatable :: file_list (:) integer :: ikey , ifile , stat logical :: is_valid if ( size ( key_list ). ge . 1 ) then do ikey = 1 , size ( key_list ) key_name = key_list ( ikey )% key if ( key_name . eq . 'flags' ) then call get_value ( table , 'flags' , flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'c-flags' ) then call get_value ( table , 'c-flags' , c_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"c-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'cxx-flags' ) then call get_value ( table , 'cxx-flags' , cxx_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"cxx-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'link-time-flags' ) then call get_value ( table , 'link-time-flags' , link_time_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"link-time-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'files' ) then call get_value ( table , 'files' , files , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"files has to be a table\" ) return end if call files % get_keys ( file_list ) do ifile = 1 , size ( file_list ) file_name = file_list ( ifile )% key call get_value ( files , file_name , file_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"file scope flags has to be a key-value pair\" ) return end if end do else if (. not . os_valid ) then call validate_os_name ( key_name , is_valid ) err_message = \"Unexpected key \" // key_name // \" found in profile table \" // profile_name // \" \" // compiler_name // \".\" if (. not . is_valid ) call syntax_error ( error , err_message ) else err_message = \"Unexpected key \" // key_name // \" found in profile table \" // profile_name // \" \" // compiler_name // \".\" call syntax_error ( error , err_message ) end if end do end if if ( allocated ( error )) return end subroutine validate_profile_table","tags":"","loc":"proc/validate_profile_table.html"},{"title":"OS_NAME – Fortran-lang/fpm","text":"public pure function OS_NAME(os) Return string describing the OS type flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: os Return Value character(len=:), allocatable Source Code pure function OS_NAME ( os ) integer , intent ( in ) :: os character ( len = :), allocatable :: OS_NAME select case ( os ) case ( OS_LINUX ); OS_NAME = \"Linux\" case ( OS_MACOS ); OS_NAME = \"macOS\" case ( OS_WINDOWS ); OS_NAME = \"Windows\" case ( OS_CYGWIN ); OS_NAME = \"Cygwin\" case ( OS_SOLARIS ); OS_NAME = \"Solaris\" case ( OS_FREEBSD ); OS_NAME = \"FreeBSD\" case ( OS_OPENBSD ); OS_NAME = \"OpenBSD\" case ( OS_UNKNOWN ); OS_NAME = \"Unknown\" case default ; OS_NAME = \"UNKNOWN\" end select end function OS_NAME","tags":"","loc":"proc/os_name.html"},{"title":"delete_env – Fortran-lang/fpm","text":"public function delete_env(name) result(success) Deletes an environment variable for the current environment using the C standard library\nReturns an error if the variable did not exist in the first place C strings Call setenv Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Variable name Return Value logical Source Code logical function delete_env ( name ) result ( success ) !> Variable name character ( * ), intent ( in ) :: name ! Local variables integer ( c_int ) :: cerr character ( kind = c_char , len = 1 ), allocatable :: c_name (:) interface integer ( c_int ) function c_unsetenv ( envname ) bind ( C , name = \"c_unsetenv\" ) import c_int , c_char implicit none !> Pointer to the name string character ( kind = c_char , len = 1 ), intent ( in ) :: envname ( * ) end function c_unsetenv end interface !> C strings call f2cs ( name , c_name ) !> Call setenv #ifndef FPM_BOOTSTRAP cerr = c_unsetenv ( c_name ) #endif success = cerr == 0_c_int end function delete_env","tags":"","loc":"proc/delete_env.html"},{"title":"get_command_arguments_quoted – Fortran-lang/fpm","text":"public function get_command_arguments_quoted() result(args) Arguments None Return Value character(len=:), allocatable Source Code function get_command_arguments_quoted () result ( args ) character ( len = :), allocatable :: args character ( len = :), allocatable :: arg character ( len = 1 ) :: quote integer :: ilength , istatus , i ilength = 0 args = '' quote = merge ( '\"' , \"'\" , separator () == '\\') do i=2,command_argument_count() ! look at all arguments after subcommand call get_command_argument(number=i,length=ilength,status=istatus) if(istatus /= 0) then write(stderr,' ( * ( g0 , 1 x )) ')' < ERROR >* get_command_arguments_stack * error obtaining argument ',i exit else if(allocated(arg))deallocate(arg) allocate(character(len=ilength) :: arg) call get_command_argument(number=i,value=arg,length=ilength,status=istatus) if(istatus /= 0) then write(stderr,' ( * ( g0 , 1 x )) ')' < ERROR >* get_command_arguments_stack * error obtaining argument ',i exit elseif(ilength>0)then if(index(arg//' ',' - ')/=1)then args=args//quote//arg//quote//' ' elseif(index(arg,' ')/=0)then args=args//quote//arg//quote//' ' else args=args//arg//' ' endif else args=args//repeat(quote,2)//' ' endif endif enddo end function get_command_arguments_quoted","tags":"","loc":"proc/get_command_arguments_quoted.html"},{"title":"get_env – Fortran-lang/fpm","text":"public function get_env(NAME, DEFAULT) result(VALUE) get named environment variable value. It it is blank or\n not set return the optional default value\n!print , NAME, ” is not defined in the environment. Strange…”\n!print , “This processor doesn’t support environment variables. Boooh!” Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: NAME name of environment variable to get the value of character(len=*), intent(in), optional :: DEFAULT default value to return if the requested value is undefined or blank Return Value character(len=:), allocatable the returned value Source Code function get_env ( NAME , DEFAULT ) result ( VALUE ) implicit none !> name of environment variable to get the value of character ( len =* ), intent ( in ) :: NAME !> default value to return if the requested value is undefined or blank character ( len =* ), intent ( in ), optional :: DEFAULT !> the returned value character ( len = :), allocatable :: VALUE integer :: howbig integer :: stat integer :: length ! get length required to hold value length = 0 if ( NAME /= '' ) then call get_environment_variable ( NAME , length = howbig , status = stat , trim_name = . true .) select case ( stat ) case ( 1 ) !*!print *, NAME, \" is not defined in the environment. Strange...\" VALUE = '' case ( 2 ) !*!print *, \"This processor doesn't support environment variables. Boooh!\" VALUE = '' case default ! make string to hold value of sufficient size allocate ( character ( len = max ( howbig , 1 )) :: VALUE ) ! get value call get_environment_variable ( NAME , VALUE , status = stat , trim_name = . true .) if ( stat /= 0 ) VALUE = '' end select else VALUE = '' endif if ( VALUE == '' . and . present ( DEFAULT )) VALUE = DEFAULT end function get_env","tags":"","loc":"proc/get_env.html"},{"title":"get_os_type – Fortran-lang/fpm","text":"public function get_os_type() result(r) Determine the OS type Returns one of OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, OS_CYGWIN,\nOS_SOLARIS, OS_FREEBSD, OS_OPENBSD. At first, the environment variable OS is checked, which is usually\nfound on Windows. Then, OSTYPE is read in and compared with common\nnames. If this fails too, check the existence of files that can be\nfound on specific system types only. Returns OS_UNKNOWN if the operating system cannot be determined. Arguments None Return Value integer Source Code integer function get_os_type () result ( r ) !! !! Returns one of OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, OS_CYGWIN, !! OS_SOLARIS, OS_FREEBSD, OS_OPENBSD. !! !! At first, the environment variable `OS` is checked, which is usually !! found on Windows. Then, `OSTYPE` is read in and compared with common !! names. If this fails too, check the existence of files that can be !! found on specific system types only. !! !! Returns OS_UNKNOWN if the operating system cannot be determined. character ( len = 255 ) :: val integer :: length , rc logical :: file_exists logical , save :: first_run = . true . integer , save :: ret = OS_UNKNOWN !$omp threadprivate(ret, first_run) if (. not . first_run ) then r = ret return end if first_run = . false . r = OS_UNKNOWN ! Check environment variable `OSTYPE`. call get_environment_variable ( 'OSTYPE' , val , length , rc ) if ( rc == 0 . and . length > 0 ) then ! Linux if ( index ( val , 'linux' ) > 0 ) then r = OS_LINUX ret = r return end if ! macOS if ( index ( val , 'darwin' ) > 0 ) then r = OS_MACOS ret = r return end if ! Windows, MSYS, MinGW, Git Bash if ( index ( val , 'win' ) > 0 . or . index ( val , 'msys' ) > 0 ) then r = OS_WINDOWS ret = r return end if ! Cygwin if ( index ( val , 'cygwin' ) > 0 ) then r = OS_CYGWIN ret = r return end if ! Solaris, OpenIndiana, ... if ( index ( val , 'SunOS' ) > 0 . or . index ( val , 'solaris' ) > 0 ) then r = OS_SOLARIS ret = r return end if ! FreeBSD if ( index ( val , 'FreeBSD' ) > 0 . or . index ( val , 'freebsd' ) > 0 ) then r = OS_FREEBSD ret = r return end if ! OpenBSD if ( index ( val , 'OpenBSD' ) > 0 . or . index ( val , 'openbsd' ) > 0 ) then r = OS_OPENBSD ret = r return end if end if ! Check environment variable `OS`. call get_environment_variable ( 'OS' , val , length , rc ) if ( rc == 0 . and . length > 0 . and . index ( val , 'Windows_NT' ) > 0 ) then r = OS_WINDOWS ret = r return end if ! Linux inquire ( file = '/etc/os-release' , exist = file_exists ) if ( file_exists ) then r = OS_LINUX ret = r return end if ! macOS inquire ( file = '/usr/bin/sw_vers' , exist = file_exists ) if ( file_exists ) then r = OS_MACOS ret = r return end if ! FreeBSD inquire ( file = '/bin/freebsd-version' , exist = file_exists ) if ( file_exists ) then r = OS_FREEBSD ret = r return end if end function get_os_type","tags":"","loc":"proc/get_os_type.html"},{"title":"os_is_unix – Fortran-lang/fpm","text":"public function os_is_unix(os) Compare the output of get_os_type or the optional\npassed INTEGER value to the value for OS_WINDOWS\nand return .TRUE. if they match and .FALSE. otherwise Arguments Type Intent Optional Attributes Name integer, intent(in), optional :: os Return Value logical Source Code logical function os_is_unix ( os ) integer , intent ( in ), optional :: os integer :: build_os if ( present ( os )) then build_os = os else build_os = get_os_type () end if os_is_unix = build_os /= OS_WINDOWS end function os_is_unix","tags":"","loc":"proc/os_is_unix.html"},{"title":"separator – Fortran-lang/fpm","text":"public function separator() result(sep) NAME separator(3f) - [M_io:ENVIRONMENT] try to determine pathname directory separator character\n(LICENSE:PD) SYNOPSIS function separator() result ( sep ) character ( len = 1 ) :: sep DESCRIPTION First using the name the program was invoked with , then the name returned by an INQUIRE ( 3 f ) of that name , then \".\\NAME\" and \"./NAME\" try to determine the separator character used to separate directory names from file basenames . If a slash or backslash is not found in the name , the environment variable PATH is examined first for a backslash , then a slash . Can be very system dependent . If the queries fail the default returned is \"/\" . EXAMPLE sample usage program demo_separator use M_io , only : separator implicit none write ( * , * ) ' separator = ' , separator () end program demo_separator !write( , )’ unknown system directory path separator’\nifort_bug*!sep_cache=sep Arguments None Return Value character(len=1) ifort_bug*!character(len=1),save :: sep_cache=’ ‘ Source Code function separator () result ( sep ) !> !!##NAME !! separator(3f) - [M_io:ENVIRONMENT] try to determine pathname directory separator character !! (LICENSE:PD) !! !!##SYNOPSIS !! !! function separator() result(sep) !! !! character(len=1) :: sep !! !!##DESCRIPTION !! First using the name the program was invoked with, then the name !! returned by an INQUIRE(3f) of that name, then \".\\NAME\" and \"./NAME\" !! try to determine the separator character used to separate directory !! names from file basenames. !! !! If a slash or backslash is not found in the name, the environment !! variable PATH is examined first for a backslash, then a slash. !! !! Can be very system dependent. If the queries fail the default returned !! is \"/\". !! !!##EXAMPLE !! !! sample usage !! !! program demo_separator !! use M_io, only : separator !! implicit none !! write(*,*)'separator=',separator() !! end program demo_separator ! use the pathname returned as arg0 to determine pathname separator implicit none character ( len = :), allocatable :: arg0 integer :: arg0_length integer :: istat logical :: existing character ( len = 1 ) :: sep !*ifort_bug*!character(len=1),save :: sep_cache=' ' character ( len = 4096 ) :: name character ( len = :), allocatable :: fname !*ifort_bug*! if(sep_cache/=' ')then ! use cached value. NOTE: A parallel code might theoretically use multiple OS !*ifort_bug*! sep=sep_cache !*ifort_bug*! return !*ifort_bug*! endif arg0_length = 0 name = ' ' call get_command_argument ( 0 , length = arg0_length , status = istat ) if ( allocated ( arg0 )) deallocate ( arg0 ) allocate ( character ( len = arg0_length ) :: arg0 ) call get_command_argument ( 0 , arg0 , status = istat ) ! check argument name if ( index ( arg0 , '\\')/=0)then sep=' \\ ' elseif(index(arg0,' / ')/=0)then sep=' / ' else ! try name returned by INQUIRE(3f) existing=.false. name=' ' inquire(file=arg0,iostat=istat,exist=existing,name=name) if(index(name,' \\ ')/=0)then sep=' \\ ' elseif(index(name,' / ')/=0)then sep=' / ' else ! well, try some common syntax and assume in current directory fname=' . \\ '//arg0 inquire(file=fname,iostat=istat,exist=existing) if(existing)then sep=' \\ ' else fname=' . / '//arg0 inquire(file=fname,iostat=istat,exist=existing) if(existing)then sep=' / ' else ! check environment variable PATH sep=merge(' \\ ',' / ',index(get_env(' PATH '),' \\ ')/=0) !*!write(*,*)' < WARNING > unknown system directory path separator ' endif endif endif endif !*ifort_bug*!sep_cache=sep end function separator","tags":"","loc":"proc/separator.html"},{"title":"set_env – Fortran-lang/fpm","text":"public function set_env(name, value, overwrite) Set an environment variable for the current environment using the C standard library Overwrite setting\nC strings\nCall setenv Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Variable name character(len=*), intent(in) :: value Variable value logical, intent(in), optional :: overwrite Should a former value be overwritten? default = .true. Return Value logical Source Code logical function set_env ( name , value , overwrite ) !> Variable name character ( * ), intent ( in ) :: name !> Variable value character ( * ), intent ( in ) :: value !> Should a former value be overwritten? default = .true. logical , optional , intent ( in ) :: overwrite ! Local variables logical :: can_overwrite integer ( c_int ) :: cover , cerr character ( kind = c_char , len = 1 ), allocatable :: c_value (:), c_name (:) interface integer ( c_int ) function c_setenv ( envname , envval , overwrite ) & bind ( C , name = \"c_setenv\" ) import c_int , c_char implicit none !> Pointer to the name string character ( kind = c_char , len = 1 ), intent ( in ) :: envname ( * ) !> Pointer to the value string character ( kind = c_char , len = 1 ), intent ( in ) :: envval ( * ) !> Overwrite option integer ( c_int ), intent ( in ), value :: overwrite end function c_setenv end interface !> Overwrite setting can_overwrite = . true . if ( present ( overwrite )) can_overwrite = overwrite cover = merge ( 1_c_int , 0_c_int , can_overwrite ) !> C strings call f2cs ( name , c_name ) call f2cs ( value , c_value ) !> Call setenv #ifndef FPM_BOOTSTRAP cerr = c_setenv ( c_name , c_value , cover ) #endif set_env = cerr == 0_c_int end function set_env","tags":"","loc":"proc/set_env.html"},{"title":"new_fortran_config – Fortran-lang/fpm","text":"public subroutine new_fortran_config(self, table, error) Construct a new build configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( fortran_config_t ), intent(out) :: self Instance of the fortran configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_fortran_config ( self , table , error ) !> Instance of the fortran configuration type ( fortran_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat character (:), allocatable :: source_form call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"implicit-typing\" , self % implicit_typing , . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'implicit-typing' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"implicit-external\" , self % implicit_external , . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'implicit-external' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"source-form\" , source_form , \"free\" , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'source-form' in fpm.toml, expecting logical\" ) return end if select case ( source_form ) case default call fatal_error ( error , \"Value of source-form cannot be '\" // source_form // \"'\" ) return case ( \"free\" , \"fixed\" , \"default\" ) self % source_form = source_form end select end subroutine new_fortran_config","tags":"","loc":"proc/new_fortran_config.html"},{"title":"name_is_json – Fortran-lang/fpm","text":"public function name_is_json(filename) Choose between JSON or TOML based on a file name Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value logical Source Code logical function name_is_json ( filename ) character ( * ), intent ( in ) :: filename character ( * ), parameter :: json_identifier = \".json\" name_is_json = . false . if ( len_trim ( filename ) < len ( json_identifier )) return name_is_json = str_ends_with ( lower ( filename ), json_identifier ) end function name_is_json","tags":"","loc":"proc/name_is_json.html"},{"title":"check_keys – Fortran-lang/fpm","text":"public subroutine check_keys(table, valid_keys, error) Check if table contains only keys that are part of the list. If a key is\nfound that is not part of the list, an error is allocated. Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: valid_keys (:) List of keys to check. type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine check_keys ( table , valid_keys , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys to check. character ( len =* ), intent ( in ) :: valid_keys (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: keys (:) type ( toml_table ), pointer :: child character (:), allocatable :: name , value , valid_keys_string integer :: ikey , ivalid call table % get_key ( name ) call table % get_keys ( keys ) do ikey = 1 , size ( keys ) if (. not . any ( keys ( ikey )% key == valid_keys )) then ! Generate error message valid_keys_string = new_line ( 'a' ) // new_line ( 'a' ) do ivalid = 1 , size ( valid_keys ) valid_keys_string = valid_keys_string // trim ( valid_keys ( ivalid )) // new_line ( 'a' ) end do allocate ( error ) error % message = \"Key '\" // keys ( ikey )% key // \"' not allowed in the '\" // & & name // \"' table.\" // new_line ( 'a' ) // new_line ( 'a' ) // 'Valid keys: ' // valid_keys_string return end if ! Check if value can be mapped or else (wrong type) show error message with the error location. ! Right now, it can only be mapped to a string or to a child node, but this can be extended in the future. call get_value ( table , keys ( ikey )% key , value ) if (. not . allocated ( value )) then ! If value is not a string, check if it is a child node call get_value ( table , keys ( ikey )% key , child ) if (. not . associated ( child )) then allocate ( error ) error % message = \"'\" // name // \"' has an invalid '\" // keys ( ikey )% key // \"' entry.\" return endif end if end do end subroutine check_keys","tags":"","loc":"proc/check_keys.html"},{"title":"get_list – Fortran-lang/fpm","text":"public subroutine get_list(table, key, list, error) Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key Key to read from type( string_t ), intent(out), allocatable :: list (:) List of strings to read type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine get_list ( table , key , list , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Key to read from character ( len =* ), intent ( in ) :: key !> List of strings to read type ( string_t ), allocatable , intent ( out ) :: list (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , ilist , nlist type ( toml_array ), pointer :: children character ( len = :), allocatable :: str if (. not . table % has_key ( key )) return call get_value ( table , key , children , requested = . false .) if ( associated ( children )) then nlist = len ( children ) allocate ( list ( nlist )) do ilist = 1 , nlist call get_value ( children , ilist , str , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Entry in \" // key // \" field cannot be read\" ) exit end if call move_alloc ( str , list ( ilist )% s ) end do if ( allocated ( error )) return else call get_value ( table , key , str , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Entry in \" // key // \" field cannot be read\" ) return end if if ( allocated ( str )) then allocate ( list ( 1 )) call move_alloc ( str , list ( 1 )% s ) end if end if end subroutine get_list","tags":"","loc":"proc/get_list.html"},{"title":"read_package_file – Fortran-lang/fpm","text":"public subroutine read_package_file(table, manifest, error) Process the configuration file to a TOML data structure Arguments Type Intent Optional Attributes Name type(toml_table), intent(out), allocatable :: table TOML data structure character(len=*), intent(in) :: manifest Name of the package configuration file type( error_t ), intent(out), allocatable :: error Error status of the operation Source Code subroutine read_package_file ( table , manifest , error ) !> TOML data structure type ( toml_table ), allocatable , intent ( out ) :: table !> Name of the package configuration file character ( len =* ), intent ( in ) :: manifest !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error type ( toml_error ), allocatable :: parse_error integer :: unit logical :: exist inquire ( file = manifest , exist = exist ) if (. not . exist ) then call file_not_found_error ( error , manifest ) return end if open ( file = manifest , newunit = unit ) call toml_load ( table , unit , error = parse_error ) close ( unit ) if ( allocated ( parse_error )) then allocate ( error ) call move_alloc ( parse_error % message , error % message ) return end if end subroutine read_package_file","tags":"","loc":"proc/read_package_file.html"},{"title":"set_list – Fortran-lang/fpm","text":"public subroutine set_list(table, key, list, error) Set no key if array is not present Check the key is not empty\nString array Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the toml table character(len=*), intent(in) :: key Key to save to type( string_t ), intent(in), allocatable :: list (:) Instance of the string array type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine set_list ( table , key , list , error ) !> Instance of the string array type ( string_t ), allocatable , intent ( in ) :: list (:) !> Key to save to character ( len =* ), intent ( in ) :: key !> Instance of the toml table type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: stat , ilist type ( toml_array ), pointer :: children character ( len = :), allocatable :: str !> Set no key if array is not present if (. not . allocated ( list )) return !> Check the key is not empty if ( len_trim ( key ) <= 0 ) then call fatal_error ( error , 'key is empty dumping string array to TOML table' ) return end if if ( size ( list ) /= 1 ) then ! includes empty list case !> String array call add_array ( table , key , children , stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Cannot set array table in \" // key // \" field\" ) return end if do ilist = 1 , size ( list ) call set_value ( children , ilist , list ( ilist )% s , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Cannot store array entry in \" // key // \" field\" ) return end if end do else ! Single value: set string call set_value ( table , key , list ( 1 )% s , stat = stat ) if ( stat /= toml_stat % success ) & call fatal_error ( error , \"Cannot store entry in \" // key // \" field\" ) return end if end subroutine set_list","tags":"","loc":"proc/set_list.html"},{"title":"add_table – Fortran-lang/fpm","text":"public interface add_table add_table: fpm interface Module Procedures private subroutine add_table_fpm(table, key, ptr, error, whereAt) Function wrapper to add a toml table and return an fpm error Nullify pointer Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key Table key type(toml_table), intent(out), pointer :: ptr The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description","tags":"","loc":"interface/add_table.html"},{"title":"get_value – Fortran-lang/fpm","text":"public interface get_value get_value: fpm interface Module Procedures private subroutine get_logical(table, key, var, error, whereAt) Function wrapper to get a logical variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key logical, intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine get_integer(table, key, var, error, whereAt) Function wrapper to get a default integer variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer, intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine get_integer_64(table, key, var, error, whereAt) Function wrapper to get a integer(int64) variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer(kind=int64), intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description","tags":"","loc":"interface/get_value.html"},{"title":"set_string – Fortran-lang/fpm","text":"public interface set_string Module Procedures private subroutine set_character(table, key, var, error, whereAt) Function wrapper to set a character(len=:), allocatable variable to a toml table Check the key is not empty Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key List of keys to check. character(len=*), intent(in), optional :: var The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_string_type(table, key, var, error, whereAt) Function wrapper to set a character(len=:), allocatable variable to a toml table Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key List of keys to check. type( string_t ), intent(in) :: var The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description","tags":"","loc":"interface/set_string.html"},{"title":"set_value – Fortran-lang/fpm","text":"public interface set_value set_value: fpm interface Module Procedures private subroutine set_logical(table, key, var, error, whereAt) Function wrapper to set a logical variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key logical, intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_integer(table, key, var, error, whereAt) Function wrapper to set a default integer variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer, intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_integer_64(table, key, var, error, whereAt) Function wrapper to set a default integer variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer(kind=int64), intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description","tags":"","loc":"interface/set_value.html"},{"title":"cmd_install – Fortran-lang/fpm","text":"public subroutine cmd_install(settings) Entry point for the fpm-install subcommand Arguments Type Intent Optional Attributes Name type( fpm_install_settings ), intent(inout) :: settings Representation of the command line settings Source Code subroutine cmd_install ( settings ) !> Representation of the command line settings type ( fpm_install_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( error_t ), allocatable :: error type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( installer_t ) :: installer type ( string_t ), allocatable :: list (:) logical :: installable integer :: ntargets call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) call build_model ( model , settings , package , error ) call handle_error ( error ) call targets_from_sources ( targets , model , settings % prune , error ) call handle_error ( error ) call install_info ( output_unit , settings % list , targets , ntargets ) if ( settings % list ) return installable = ( allocated ( package % library ) . and . package % install % library ) & . or . allocated ( package % executable ) . or . ntargets > 0 if (. not . installable ) then call fatal_error ( error , \"Project does not contain any installable targets\" ) call handle_error ( error ) end if if (. not . settings % no_rebuild ) then call build_package ( targets , model , verbose = settings % verbose ) end if call new_installer ( installer , prefix = settings % prefix , & bindir = settings % bindir , libdir = settings % libdir , & includedir = settings % includedir , & verbosity = merge ( 2 , 1 , settings % verbose )) if ( allocated ( package % library ) . and . package % install % library ) then call filter_library_targets ( targets , list ) if ( size ( list ) > 0 ) then call installer % install_library ( list ( 1 )% s , error ) call handle_error ( error ) call install_module_files ( installer , targets , error ) call handle_error ( error ) end if end if if ( allocated ( package % executable ) . or . ntargets > 0 ) then call install_executables ( installer , targets , error ) call handle_error ( error ) end if end subroutine cmd_install","tags":"","loc":"proc/cmd_install.html"},{"title":"new_installer – Fortran-lang/fpm","text":"public subroutine new_installer(self, prefix, bindir, libdir, includedir, verbosity, copy, move) Create a new instance of an installer Arguments Type Intent Optional Attributes Name type( installer_t ), intent(out) :: self Instance of the installer character(len=*), intent(in), optional :: prefix Path to installation directory character(len=*), intent(in), optional :: bindir Binary dir relative to the installation prefix character(len=*), intent(in), optional :: libdir Library directory relative to the installation prefix character(len=*), intent(in), optional :: includedir Include directory relative to the installation prefix integer, intent(in), optional :: verbosity Verbosity of the installer character(len=*), intent(in), optional :: copy Copy command character(len=*), intent(in), optional :: move Move command Source Code subroutine new_installer ( self , prefix , bindir , libdir , includedir , verbosity , & copy , move ) !> Instance of the installer type ( installer_t ), intent ( out ) :: self !> Path to installation directory character ( len =* ), intent ( in ), optional :: prefix !> Binary dir relative to the installation prefix character ( len =* ), intent ( in ), optional :: bindir !> Library directory relative to the installation prefix character ( len =* ), intent ( in ), optional :: libdir !> Include directory relative to the installation prefix character ( len =* ), intent ( in ), optional :: includedir !> Verbosity of the installer integer , intent ( in ), optional :: verbosity !> Copy command character ( len =* ), intent ( in ), optional :: copy !> Move command character ( len =* ), intent ( in ), optional :: move self % os = get_os_type () ! By default, never prompt the user for overwrites if ( present ( copy )) then self % copy = copy else if ( os_is_unix ( self % os )) then self % copy = default_force_copy_unix else self % copy = default_force_copy_win end if end if if ( present ( move )) then self % move = move else if ( os_is_unix ( self % os )) then self % move = default_move_unix else self % move = default_move_win end if end if if ( present ( includedir )) then self % includedir = includedir else self % includedir = default_includedir end if if ( present ( prefix )) then self % prefix = prefix else self % prefix = get_local_prefix ( self % os ) end if if ( present ( bindir )) then self % bindir = bindir else self % bindir = default_bindir end if if ( present ( libdir )) then self % libdir = libdir else self % libdir = default_libdir end if if ( present ( verbosity )) then self % verbosity = verbosity else self % verbosity = 1 end if end subroutine new_installer","tags":"","loc":"proc/new_installer.html"},{"title":"dilate – Fortran-lang/fpm","text":"public function dilate(instr) result(outstr) NAME dilate(3f) - [M_strings:NONALPHA] expand tab characters\n(LICENSE:PD) SYNOPSIS function dilate(INSTR) result ( OUTSTR ) character ( len = * ), intent =( in ) :: INSTR character ( len =:), allocatable :: OUTSTR DESCRIPTION dilate() converts tabs in INSTR to spaces in OUTSTR. It assumes a\n tab is set every 8 characters. Trailing spaces are removed.\n\n In addition, trailing carriage returns and line feeds are removed\n (they are usually a problem created by going to and from MSWindows). OPTIONS instr Input line to remove tabs from RESULTS outstr Output string with tabs expanded. EXAMPLES Sample program: program demo_dilate use M_strings , only : dilate implicit none character ( len =:), allocatable :: in integer :: i in = ' this is my string ' ! change spaces to tabs to make a sample input do i = 1 , len ( in ) if ( in ( i : i ) == ' ' ) in ( i : i )= char ( 9 ) enddo write ( * , ' ( a ) ' ) in , dilate ( in ) end program demo_dilate Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: instr Return Value character(len=:), allocatable Source Code function dilate ( instr ) result ( outstr ) character ( len =* ), intent ( in ) :: instr ! input line to scan for tab characters character ( len = :), allocatable :: outstr ! tab-expanded version of INSTR produced integer :: i integer :: icount integer :: lgth icount = 0 do i = 1 , len ( instr ) if ( instr ( i : i ) == char ( 9 )) icount = icount + 1 end do allocate ( character ( len = ( len ( instr ) + 8 * icount )) :: outstr ) call notabs ( instr , outstr , lgth ) outstr = outstr (: lgth ) end function dilate","tags":"","loc":"proc/dilate.html"},{"title":"f_string – Fortran-lang/fpm","text":"public function f_string(c_string) Uses iso_c_binding return Fortran character variable when given a C-like array of\nsingle characters terminated with a C_NULL_CHAR character Arguments Type Intent Optional Attributes Name character(len=1), intent(in) :: c_string (:) Return Value character(len=:), allocatable Source Code function f_string ( c_string ) use iso_c_binding character ( len = 1 ), intent ( in ) :: c_string (:) character (:), allocatable :: f_string integer :: i , n i = 0 do while ( c_string ( i + 1 ) /= C_NULL_CHAR ) i = i + 1 end do n = i allocate ( character ( n ) :: f_string ) do i = 1 , n f_string ( i : i ) = c_string ( i ) end do end function f_string","tags":"","loc":"proc/f_string.html"},{"title":"glob – Fortran-lang/fpm","text":"public function glob(tame, wild) NAME glob(3f) - [fpm_strings:COMPARE] compare given string for match to\npattern which may contain wildcard characters\n(LICENSE:PD) SYNOPSIS logical function glob(string, pattern )\n\n character(len=*),intent(in) :: string\n character(len=*),intent(in) :: pattern DESCRIPTION glob(3f) compares given STRING for match to PATTERN which may\n contain wildcard characters. In this version to get a match the entire string must be described\n by PATTERN. Trailing whitespace is significant, so trim the input\n string to have trailing whitespace ignored. OPTIONS string the input string to test to see if it contains the pattern . pattern the following simple globbing options are available o \"?\" matching any one character o \"*\" matching zero or more characters . Do NOT use adjacent asterisks . o Both strings may have trailing spaces which are ignored . o There is no escape character , so matching strings with literal question mark and asterisk is problematic . EXAMPLES Example program program demo_glob implicit none ! This main () routine passes a bunch of test strings ! into the above code . In performance comparison mode , ! it does that over and over . Otherwise , it does it just ! once . Either way , it outputs a passed / failed result . ! integer :: nReps logical :: allpassed integer :: i allpassed = . true . nReps = 10000 ! Can choose as many repetitions as you ' re expecting ! in the real world . nReps = 1 do i = 1 , nReps ! Cases with repeating character sequences . allpassed = allpassed . and . test ( \"a*abab\" , \"a*b\" , . true .) !! cycle allpassed = allpassed . and . test ( \"ab\" , \"*?\" , . true .) allpassed = allpassed . and . test ( \"abc\" , \"*?\" , . true .) allpassed = allpassed . and . test ( \"abcccd\" , \"*ccd\" , . true .) allpassed = allpassed . and . test ( \"bLah\" , \"bLaH\" , . false .) allpassed = allpassed . and . test ( \"mississippi\" , \"*sip*\" , . true .) allpassed = allpassed . and . & & test ( \"xxxx*zzzzzzzzy*f\" , \"xxx*zzy*f\" , . true .) allpassed = allpassed . and . & & test ( \"xxxx*zzzzzzzzy*f\" , \"xxxx*zzy*fffff\" , . false .) allpassed = allpassed . and . & & test ( \"mississipissippi\" , \"*issip*ss*\" , . true .) allpassed = allpassed . and . & & test ( \"xxxxzzzzzzzzyf\" , \"xxxx*zzy*fffff\" , . false .) allpassed = allpassed . and . & & test ( \"xxxxzzzzzzzzyf\" , \"xxxx*zzy*f\" , . true .) allpassed = allpassed . and . test ( \"xyxyxyzyxyz\" , \"xy*z*xyz\" , . true .) allpassed = allpassed . and . test ( \"xyxyxyxyz\" , \"xy*xyz\" , . true .) allpassed = allpassed . and . test ( \"mississippi\" , \"mi*sip*\" , . true .) allpassed = allpassed . and . test ( \"ababac\" , \"*abac*\" , . true .) allpassed = allpassed . and . test ( \"aaazz\" , \"a*zz*\" , . true .) allpassed = allpassed . and . test ( \"a12b12\" , \"*12*23\" , . false .) allpassed = allpassed . and . test ( \"a12b12\" , \"a12b\" , . false .) allpassed = allpassed . and . test ( \"a12b12\" , \"*12*12*\" , . true .) ! Additional cases where the '*' char appears in the tame string . allpassed = allpassed . and . test ( \"*\" , \"*\" , . true .) allpassed = allpassed . and . test ( \"a*r\" , \"a*\" , . true .) allpassed = allpassed . and . test ( \"a*ar\" , \"a*aar\" , . false .) ! More double wildcard scenarios . allpassed = allpassed . and . test ( \"XYXYXYZYXYz\" , \"XY*Z*XYz\" , . true .) allpassed = allpassed . and . test ( \"missisSIPpi\" , \"*SIP*\" , . true .) allpassed = allpassed . and . test ( \"mississipPI\" , \"*issip*PI\" , . true .) allpassed = allpassed . and . test ( \"xyxyxyxyz\" , \"xy*xyz\" , . true .) allpassed = allpassed . and . test ( \"miSsissippi\" , \"mi*sip*\" , . true .) allpassed = allpassed . and . test ( \"miSsissippi\" , \"mi*Sip*\" , . false .) allpassed = allpassed . and . test ( \"abAbac\" , \"*Abac*\" , . true .) allpassed = allpassed . and . test ( \"aAazz\" , \"a*zz*\" , . true .) allpassed = allpassed . and . test ( \"A12b12\" , \"*12*23\" , . false .) allpassed = allpassed . and . test ( \"a12B12\" , \"*12*12*\" , . true .) allpassed = allpassed . and . test ( \"oWn\" , \"*oWn*\" , . true .) ! Completely tame ( no wildcards ) cases . allpassed = allpassed . and . test ( \"bLah\" , \"bLah\" , . true .) ! Simple mixed wildcard tests suggested by IBMer Marlin Deckert . allpassed = allpassed . and . test ( \"a\" , \"*?\" , . true .) ! More mixed wildcard tests including coverage for false positives . allpassed = allpassed . and . test ( \"a\" , \"??\" , . false .) allpassed = allpassed . and . test ( \"ab\" , \"?*?\" , . true .) allpassed = allpassed . and . test ( \"ab\" , \"*?*?*\" , . true .) allpassed = allpassed . and . test ( \"abc\" , \"?**?*?\" , . true .) allpassed = allpassed . and . test ( \"abc\" , \"?**?*&?\" , . false .) allpassed = allpassed . and . test ( \"abcd\" , \"?b*??\" , . true .) allpassed = allpassed . and . test ( \"abcd\" , \"?a*??\" , . false .) allpassed = allpassed . and . test ( \"abcd\" , \"?**?c?\" , . true .) allpassed = allpassed . and . test ( \"abcd\" , \"?**?d?\" , . false .) allpassed = allpassed . and . test ( \"abcde\" , \"?*b*?*d*?\" , . true .) ! Single - character - match cases . allpassed = allpassed . and . test ( \"bLah\" , \"bL?h\" , . true .) allpassed = allpassed . and . test ( \"bLaaa\" , \"bLa?\" , . false .) allpassed = allpassed . and . test ( \"bLah\" , \"bLa?\" , . true .) allpassed = allpassed . and . test ( \"bLaH\" , \"?Lah\" , . false .) allpassed = allpassed . and . test ( \"bLaH\" , \"?LaH\" , . true .) ! Many - wildcard scenarios . allpassed = allpassed . and . test ( & & \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa& &aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab\" , & & \"a*a*a*a*a*a*aa*aaa*a*a*b\" , & & . true .) allpassed = allpassed . and . test ( & & \"abababababababababababababababababababaacacacacacacac& &adaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\" , & & \"*a*b*ba*ca*a*aa*aaa*fa*ga*b*\" , & & . true .) allpassed = allpassed . and . test ( & & \"abababababababababababababababababababaacacacacacaca& &cadaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\" , & & \"*a*b*ba*ca*a*x*aaa*fa*ga*b*\" , & & . false .) allpassed = allpassed . and . test ( & & \"abababababababababababababababababababaacacacacacacacad& &aeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\" , & & \"*a*b*ba*ca*aaaa*fa*ga*gggg*b*\" , & & . false .) allpassed = allpassed . and . test ( & & \"abababababababababababababababababababaacacacacacacacad& &aeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\" , & & \"*a*b*ba*ca*aaaa*fa*ga*ggg*b*\" , & & . true .) allpassed = allpassed . and . test ( \"aaabbaabbaab\" , \"*aabbaa*a*\" , . true .) allpassed = allpassed . and . & test ( \"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\" , & & \"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\" , . true .) allpassed = allpassed . and . test ( \"aaaaaaaaaaaaaaaaa\" , & & \"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\" , . true .) allpassed = allpassed . and . test ( \"aaaaaaaaaaaaaaaa\" , & & \"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\" , . false .) allpassed = allpassed . and . test ( & & \"abc*abcd*abcde*abcdef*abcdefg*abcdefgh*abcdefghi*abcdefghij& &*abcdefghijk*abcdefghijkl*abcdefghijklm*abcdefghijklmn\" , & & \"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc& &*abc*abc*abc*\" , & & . false .) allpassed = allpassed . and . test ( & & \"abc*abcd*abcde*abcdef*abcdefg*abcdefgh*abcdefghi*abcdefghij& &*abcdefghijk*abcdefghijkl*abcdefghijklm*abcdefghijklmn\" , & & \"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*\" , & & . true .) allpassed = allpassed . and . test ( \"abc*abcd*abcd*abc*abcd\" , & & \"abc*abc*abc*abc*abc\" , . false .) allpassed = allpassed . and . test ( \"abc*abcd*abcd*abc*abcd*abcd& &*abc*abcd*abc*abc*abcd\" , & & \"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abcd\" , & & . true .) allpassed = allpassed . and . test ( \"abc\" , & & \"********a********b********c********\" , . true .) allpassed = allpassed . and . & & test ( \"********a********b********c********\" , \"abc\" , . false .) allpassed = allpassed . and . & & test ( \"abc\" , \"********a********b********b********\" , . false .) allpassed = allpassed . and . test ( \"*abc*\" , \"***a*b*c***\" , . true .) ! A case - insensitive algorithm test . ! allpassed = allpassed . and . test ( \"mississippi\" , \"*issip*PI\" , . true .) enddo if ( allpassed ) then write ( * , ' ( a ) ' ) \"Passed\" , nReps else write ( * , ' ( a ) ' ) \"Failed\" endif contains ! This is a test program for wildcard matching routines . ! It can be used either to test a single routine for correctness , ! or to compare the timings of two ( or more ) different wildcard ! matching routines . ! function test ( tame , wild , bExpectedResult ) result ( bpassed ) use fpm_strings , only : glob character ( len = * ) :: tame character ( len = * ) :: wild logical :: bExpectedResult logical :: bResult logical :: bPassed bResult = . true . ! We ' ll do \"&=\" cumulative checking . bPassed = . false . ! Assume the worst . write ( * , * ) repeat ( '=' , 79 ) bResult = glob ( tame , wild ) ! Call a wildcard matching routine . ! To assist correctness checking , output the two strings in any ! failing scenarios . if ( bExpectedResult . eqv . bResult ) then bPassed = . true . if ( nReps == 1 ) write ( * , * ) \"Passed match on \" , tame , \" vs. \" , wild else if ( nReps == 1 ) write ( * , * ) \"Failed match on \" , tame , \" vs. \" , wild endif end function test end program demo_glob Expected output REFERENCE The article “Matching Wildcards: An Empirical Way to Tame an Algorithm”\n in Dr Dobb’s Journal, By Kirk J. Krauss, October 07, 2014 Arguments Type Intent Optional Attributes Name character(len=*) :: tame A string without wildcards to compare to the globbing expression character(len=*) :: wild A (potentially) corresponding string with wildcards Return Value logical result of test Source Code function glob ( tame , wild ) ! @(#)fpm_strings::glob(3f): function compares text strings, one of which can have wildcards ('*' or '?'). logical :: glob !! result of test character ( len =* ) :: tame !! A string without wildcards to compare to the globbing expression character ( len =* ) :: wild !! A (potentially) corresponding string with wildcards character ( len = len ( tame ) + 1 ) :: tametext character ( len = len ( wild ) + 1 ) :: wildtext character ( len = 1 ), parameter :: NULL = char ( 0 ) integer :: wlen integer :: ti , wi integer :: i character ( len = :), allocatable :: tbookmark , wbookmark ! These two values are set when we observe a wildcard character. They ! represent the locations, in the two strings, from which we start once we've observed it. tametext = tame // NULL wildtext = wild // NULL tbookmark = NULL wbookmark = NULL wlen = len ( wild ) wi = 1 ti = 1 do ! Walk the text strings one character at a time. if ( wildtext ( wi : wi ) == '*' ) then ! How do you match a unique text string? do i = wi , wlen ! Easy: unique up on it! if ( wildtext ( wi : wi ) == '*' ) then wi = wi + 1 else exit endif enddo if ( wildtext ( wi : wi ) == NULL ) then ! \"x\" matches \"*\" glob = . true . return endif if ( wildtext ( wi : wi ) /= '?' ) then ! Fast-forward to next possible match. do while ( tametext ( ti : ti ) /= wildtext ( wi : wi )) ti = ti + 1 if ( tametext ( ti : ti ) == NULL ) then glob = . false . return ! \"x\" doesn't match \"*y*\" endif enddo endif wbookmark = wildtext ( wi :) tbookmark = tametext ( ti :) elseif ( tametext ( ti : ti ) /= wildtext ( wi : wi ) . and . wildtext ( wi : wi ) /= '?' ) then ! Got a non-match. If we've set our bookmarks, back up to one or both of them and retry. if ( wbookmark /= NULL ) then if ( wildtext ( wi :) /= wbookmark ) then wildtext = wbookmark ; wlen = len_trim ( wbookmark ) wi = 1 ! Don't go this far back again. if ( tametext ( ti : ti ) /= wildtext ( wi : wi )) then tbookmark = tbookmark ( 2 :) tametext = tbookmark ti = 1 cycle ! \"xy\" matches \"*y\" else wi = wi + 1 endif endif if ( tametext ( ti : ti ) /= NULL ) then ti = ti + 1 cycle ! \"mississippi\" matches \"*sip*\" endif endif glob = . false . return ! \"xy\" doesn't match \"x\" endif ti = ti + 1 wi = wi + 1 if ( tametext ( ti : ti ) == NULL ) then ! How do you match a tame text string? if ( wildtext ( wi : wi ) /= NULL ) then do while ( wildtext ( wi : wi ) == '*' ) ! The tame way: unique up on it! wi = wi + 1 ! \"x\" matches \"x*\" if ( wildtext ( wi : wi ) == NULL ) exit enddo endif if ( wildtext ( wi : wi ) == NULL ) then glob = . true . return ! \"x\" matches \"x\" endif glob = . false . return ! \"x\" doesn't match \"xy\" endif enddo end function glob","tags":"","loc":"proc/glob.html"},{"title":"has_valid_custom_prefix – Fortran-lang/fpm","text":"public function has_valid_custom_prefix(module_name, custom_prefix) result(valid) Check that a module name is prefixed with a custom prefix:\n1) It must be a valid FORTRAN name subset (<=63 chars, begin with letter, only alphanumeric allowed)\n2) It must begin with the prefix\n3) If longer, package name must be followed by default separator (“_”) plus at least one char Basic check: check that both names are individually valid FPM package enforcing: check that the module name begins with the custom prefix Query string lengths\n2) It must begin with the package name.\n3) It can be equal to the package name, or, if longer, must be followed by the\n4) Package name must not end with an underscore Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: custom_prefix Return Value logical Source Code logical function has_valid_custom_prefix ( module_name , custom_prefix ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: custom_prefix !> custom_module separator: single underscore character ( * ), parameter :: SEP = \"_\" logical :: is_same , has_separator , same_beginning integer :: lpkg , lmod , lsep !> Basic check: check that both names are individually valid valid = is_fortran_name ( module_name % s ) . and . & is_valid_module_prefix ( custom_prefix ) !> FPM package enforcing: check that the module name begins with the custom prefix if ( valid ) then !> Query string lengths lpkg = len_trim ( custom_prefix ) lmod = len_trim ( module_name ) lsep = len_trim ( SEP ) same_beginning = str_begins_with_str ( module_name % s , custom_prefix % s , case_sensitive = . false .) is_same = lpkg == lmod . and . same_beginning if ( lmod >= lpkg + lsep ) then has_separator = str_begins_with_str ( module_name % s ( lpkg + 1 : lpkg + lsep ), SEP ) else has_separator = . false . endif !> 2) It must begin with the package name. !> 3) It can be equal to the package name, or, if longer, must be followed by the ! default separator plus at least one character !> 4) Package name must not end with an underscore valid = same_beginning . and . ( is_same . or . ( lmod > lpkg + lsep . and . has_separator )) end if end function has_valid_custom_prefix","tags":"","loc":"proc/has_valid_custom_prefix.html"},{"title":"has_valid_standard_prefix – Fortran-lang/fpm","text":"public function has_valid_standard_prefix(module_name, package_name) result(valid) Check that a module name is prefixed with the default package prefix:\n1) It must be a valid FORTRAN name (<=63 chars, begin with letter, “_” is only allowed non-alphanumeric)\n2) It must begin with the package name\n3) If longer, package name must be followed by default separator plus at least one char Basic check: check the name is Fortran-compliant FPM package enforcing: check that the module name begins with the package name Query string lengths\n2) It must begin with the package name.\n3) It can be equal to the package name, or, if longer, must be followed by the\n4) Package name must not end with an underscore Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: package_name Return Value logical Source Code logical function has_valid_standard_prefix ( module_name , package_name ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: package_name !> Default package__module separator: two underscores character ( * ), parameter :: SEP = \"__\" character ( len = :), allocatable :: fortranized_pkg logical :: is_same , has_separator , same_beginning integer :: lpkg , lmod , lsep !> Basic check: check the name is Fortran-compliant valid = is_fortran_name ( module_name % s ) !> FPM package enforcing: check that the module name begins with the package name if ( valid ) then fortranized_pkg = to_fortran_name ( package_name % s ) !> Query string lengths lpkg = len_trim ( fortranized_pkg ) lmod = len_trim ( module_name ) lsep = len_trim ( SEP ) same_beginning = str_begins_with_str ( module_name % s , fortranized_pkg , case_sensitive = . false .) is_same = lpkg == lmod . and . same_beginning if ( lmod >= lpkg + lsep ) then has_separator = str_begins_with_str ( module_name % s ( lpkg + 1 : lpkg + lsep ), SEP ) else has_separator = . false . endif !> 2) It must begin with the package name. !> 3) It can be equal to the package name, or, if longer, must be followed by the ! default separator plus at least one character !> 4) Package name must not end with an underscore valid = is_fortran_name ( fortranized_pkg ) . and . & fortranized_pkg ( lpkg : lpkg ) /= '_' . and . & ( same_beginning . and . ( is_same . or . ( lmod > lpkg + lsep . and . has_separator ))) end if end function has_valid_standard_prefix","tags":"","loc":"proc/has_valid_standard_prefix.html"},{"title":"is_fortran_name – Fortran-lang/fpm","text":"public elemental function is_fortran_name(line) result(lout) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: line Return Value logical Source Code elemental function is_fortran_name ( line ) result ( lout ) ! determine if a string is a valid Fortran name ignoring trailing spaces ! (but not leading spaces) character ( len =* ), parameter :: int = '0123456789' character ( len =* ), parameter :: lower = 'abcdefghijklmnopqrstuvwxyz' character ( len =* ), parameter :: upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' character ( len =* ), parameter :: allowed = upper // lower // int // '_' character ( len =* ), intent ( in ) :: line character ( len = :), allocatable :: name logical :: lout name = trim ( line ) if ( len ( name ) /= 0 ) then lout = . true . & & . and . verify ( name ( 1 : 1 ), lower // upper ) == 0 & & . and . verify ( name , allowed ) == 0 & & . and . len ( name ) <= 63 else lout = . false . endif end function is_fortran_name","tags":"","loc":"proc/is_fortran_name.html"},{"title":"is_valid_module_name – Fortran-lang/fpm","text":"public function is_valid_module_name(module_name, package_name, custom_prefix, enforce_module_names) result(valid) Check that a module name fits the current naming rules:\n1) It must be a valid FORTRAN name (<=63 chars, begin with letter, “_” is only allowed non-alphanumeric)\n2) It must begin with the package name\n3) If longer, package name must be followed by default separator plus at least one char Basic check: check the name is Fortran-compliant FPM package enforcing: check that the module name begins with the package name Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: package_name type( string_t ), intent(in) :: custom_prefix logical, intent(in) :: enforce_module_names Return Value logical Source Code logical function is_valid_module_name ( module_name , package_name , custom_prefix , enforce_module_names ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: package_name type ( string_t ), intent ( in ) :: custom_prefix logical , intent ( in ) :: enforce_module_names !> Basic check: check the name is Fortran-compliant valid = is_fortran_name ( module_name % s ); if (. not . valid ) return !> FPM package enforcing: check that the module name begins with the package name if ( enforce_module_names ) then ! Default prefixing is always valid valid = has_valid_standard_prefix ( module_name , package_name ) ! If a custom prefix was validated, it provides additional naming options ! Because they never overlap with the default prefix, the former is always an option if ( len_trim ( custom_prefix ) > 0 . and . . not . valid ) & valid = has_valid_custom_prefix ( module_name , custom_prefix ) end if end function is_valid_module_name","tags":"","loc":"proc/is_valid_module_name.html"},{"title":"is_valid_module_prefix – Fortran-lang/fpm","text":"public function is_valid_module_prefix(module_prefix) result(valid) Check that a custom module prefix fits the current naming rules:\n1) Only alphanumeric characters (no spaces, dashes, underscores or other characters)\n2) Does not begin with a number (Fortran-compatible syntax) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_prefix Return Value logical Source Code logical function is_valid_module_prefix ( module_prefix ) result ( valid ) type ( string_t ), intent ( in ) :: module_prefix character ( len =* ), parameter :: num = '0123456789' character ( len =* ), parameter :: lower = 'abcdefghijklmnopqrstuvwxyz' character ( len =* ), parameter :: upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' character ( len =* ), parameter :: alpha = upper // lower character ( len =* ), parameter :: allowed = alpha // num character ( len = :), allocatable :: name name = trim ( module_prefix % s ) if ( len ( name ) > 0 . and . len ( name ) <= 63 ) then valid = verify ( name ( 1 : 1 ), alpha ) == 0 . and . & verify ( name , allowed ) == 0 else valid = . false . endif end function is_valid_module_prefix","tags":"","loc":"proc/is_valid_module_prefix.html"},{"title":"join – Fortran-lang/fpm","text":"public pure function join(str, sep, trm, left, right, start, end) result(string) NAME join ( 3 f ) - [ M_strings : EDITING ] append CHARACTER variable array into a single CHARACTER variable with specified separator ( LICENSE : PD ) SYNOPSIS pure function join(str,sep,trm,left,right,start,end) result (string)\n\n character(len=*),intent(in) :: str(:)\n character(len=*),intent(in),optional :: sep\n logical,intent(in),optional :: trm\n character(len=*),intent(in),optional :: right\n character(len=*),intent(in),optional :: left\n character(len=*),intent(in),optional :: start\n character(len=*),intent(in),optional :: end\n character(len=:),allocatable :: string DESCRIPTION JOIN(3f) appends the elements of a CHARACTER array into a single\n CHARACTER variable, with elements 1 to N joined from left to right.\n By default each element is trimmed of trailing spaces and the\n default separator is a null string. OPTIONS STR (:) array of CHARACTER variables to be joined SEP separator string to place between each variable . defaults to a null string . LEFT string to place at left of each element RIGHT string to place at right of each element START prefix string END suffix string TRM option to trim each element of STR of trailing spaces . Defaults to . TRUE . RESULT STRING CHARACTER variable composed of all of the elements of STR () appended together with the optional separator SEP placed between the elements . EXAMPLE Sample program: program demo_join\n use M_strings, only: join\n implicit none\n character(len=:),allocatable :: s(:)\n character(len=:),allocatable :: out\n integer :: i\n s=[character(len=10) :: ‘United’,’ we’,’ stand,’, &\n & ’ divided’,’ we fall.’]\n out=join(s)\n write( ,’(a)’) out\n write( ,’(a)’) join(s,trm=.false.)\n write( ,’(a)’) (join(s,trm=.false.,sep=’|’),i=1,3)\n write( ,’(a)’) join(s,sep=’<>’)\n write( ,’(a)’) join(s,sep=’;’,left=’[‘,right=’]’)\n write( ,’(a)’) join(s,left=’[‘,right=’]’)\n write(*,’(a)’) join(s,left=’>>’)\n end program demo_join Expected output: United we stand, divided we fall.\n United we stand, divided we fall.\n United | we | stand, | divided | we fall.\n United | we | stand, | divided | we fall.\n United | we | stand, | divided | we fall.\n United<> we<> stand,<> divided<> we fall.\n [United];[ we];[ stand,];[ divided];[ we fall.]\n [United][ we][ stand,][ divided][ we fall.] United>> we>> stand,>> divided>> we fall. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str (:) character(len=*), intent(in), optional :: sep logical, intent(in), optional :: trm character(len=*), intent(in), optional :: left character(len=*), intent(in), optional :: right character(len=*), intent(in), optional :: start character(len=*), intent(in), optional :: end Return Value character(len=:), allocatable Source Code pure function join ( str , sep , trm , left , right , start , end ) result ( string ) ! @(#)M_strings::join(3f): merge string array into a single CHARACTER value adding specified separators, caps, prefix and suffix character ( len =* ), intent ( in ) :: str (:) character ( len =* ), intent ( in ), optional :: sep , right , left , start , end logical , intent ( in ), optional :: trm character ( len = :), allocatable :: sep_local , left_local , right_local character ( len = :), allocatable :: string logical :: trm_local integer :: i if ( present ( sep )) then ; sep_local = sep ; else ; sep_local = '' ; endif if ( present ( trm )) then ; trm_local = trm ; else ; trm_local = . true . ; endif if ( present ( left )) then ; left_local = left ; else ; left_local = '' ; endif if ( present ( right )) then ; right_local = right ; else ; right_local = '' ; endif string = '' if ( size ( str ) == 0 ) then string = string // left_local // right_local else do i = 1 , size ( str ) - 1 if ( trm_local ) then string = string // left_local // trim ( str ( i )) // right_local // sep_local else string = string // left_local // str ( i ) // right_local // sep_local endif enddo if ( trm_local ) then string = string // left_local // trim ( str ( i )) // right_local else string = string // left_local // str ( i ) // right_local endif endif if ( present ( start )) string = start // string if ( present ( end )) string = string // end end function join","tags":"","loc":"proc/join.html"},{"title":"lower – Fortran-lang/fpm","text":"public pure elemental function lower(str, begin, end) result(string) Changes a string to lowercase over optional specified column range Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str integer, intent(in), optional :: begin integer, intent(in), optional :: end Return Value character(len=len(str)) Source Code elemental pure function lower ( str , begin , end ) result ( string ) character ( * ), intent ( In ) :: str character ( len ( str )) :: string integer , intent ( in ), optional :: begin , end integer :: i integer :: ibegin , iend string = str ibegin = 1 if ( present ( begin )) then ibegin = max ( ibegin , begin ) endif iend = len_trim ( str ) if ( present ( end )) then iend = min ( iend , end ) endif do i = ibegin , iend ! step thru each letter in the string in specified range select case ( str ( i : i )) case ( 'A' : 'Z' ) string ( i : i ) = char ( iachar ( str ( i : i )) + 32 ) ! change letter to miniscule case default end select end do end function lower","tags":"","loc":"proc/lower.html"},{"title":"module_prefix_template – Fortran-lang/fpm","text":"public function module_prefix_template(project_name, custom_prefix) result(prefix) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: project_name type( string_t ), intent(in) :: custom_prefix Return Value type( string_t ) Source Code type ( string_t ) function module_prefix_template ( project_name , custom_prefix ) result ( prefix ) type ( string_t ), intent ( in ) :: project_name type ( string_t ), intent ( in ) :: custom_prefix if ( is_valid_module_prefix ( custom_prefix )) then prefix = string_t ( trim ( custom_prefix % s ) // \"_\" ) else prefix = string_t ( to_fortran_name ( project_name % s ) // \"__\" ) end if end function module_prefix_template","tags":"","loc":"proc/module_prefix_template.html"},{"title":"module_prefix_type – Fortran-lang/fpm","text":"public function module_prefix_type(project_name, custom_prefix) result(ptype) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: project_name type( string_t ), intent(in) :: custom_prefix Return Value type( string_t ) Source Code type ( string_t ) function module_prefix_type ( project_name , custom_prefix ) result ( ptype ) type ( string_t ), intent ( in ) :: project_name type ( string_t ), intent ( in ) :: custom_prefix if ( is_valid_module_prefix ( custom_prefix )) then ptype = string_t ( \"custom\" ) else ptype = string_t ( \"default\" ) end if end function module_prefix_type","tags":"","loc":"proc/module_prefix_type.html"},{"title":"replace – Fortran-lang/fpm","text":"public pure function replace(string, charset, target_char) result(res) Returns string with characters in charset replaced with target_char. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string character(len=1), intent(in) :: charset (:) character(len=1), intent(in) :: target_char Return Value character(len=len(string)) Source Code pure function replace ( string , charset , target_char ) result ( res ) character ( * ), intent ( in ) :: string character , intent ( in ) :: charset (:), target_char character ( len ( string )) :: res integer :: n res = string do n = 1 , len ( string ) if ( any ( string ( n : n ) == charset )) then res ( n : n ) = target_char end if end do end function replace","tags":"","loc":"proc/replace.html"},{"title":"str_begins_with_str – Fortran-lang/fpm","text":"public pure function str_begins_with_str(s, e, case_sensitive) result(r) test if a CHARACTER string begins with a specified prefix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e logical, intent(in), optional :: case_sensitive Return Value logical Source Code pure logical function str_begins_with_str ( s , e , case_sensitive ) result ( r ) character ( * ), intent ( in ) :: s , e logical , optional , intent ( in ) :: case_sensitive ! Default option: case sensitive integer :: n1 , n2 logical :: lower_case ! Check if case sensitive if ( present ( case_sensitive )) then lower_case = . not . case_sensitive else lower_case = . false . end if n1 = 1 n2 = 1 + len ( e ) - 1 if ( n2 > len ( s )) then r = . false . elseif ( lower_case ) then r = lower ( s ( n1 : n2 )) == lower ( e ) else r = ( s ( n1 : n2 ) == e ) end if end function str_begins_with_str","tags":"","loc":"proc/str_begins_with_str.html"},{"title":"string_array_contains – Fortran-lang/fpm","text":"public function string_array_contains(search_string, array) Check if array of TYPE(STRING_T) matches a particular CHARACTER string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: search_string type( string_t ), intent(in) :: array (:) Return Value logical Source Code logical function string_array_contains ( search_string , array ) character ( * ), intent ( in ) :: search_string type ( string_t ), intent ( in ) :: array (:) integer :: i string_array_contains = any ([( array ( i )% s == search_string , & i = 1 , size ( array ))]) end function string_array_contains","tags":"","loc":"proc/string_array_contains.html"},{"title":"string_cat – Fortran-lang/fpm","text":"public function string_cat(strings, delim) result(cat) Concatenate an array of type(string_t) into\n a single CHARACTER variable Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: strings (:) character(len=*), intent(in), optional :: delim Return Value character(len=:), allocatable Source Code function string_cat ( strings , delim ) result ( cat ) type ( string_t ), intent ( in ) :: strings (:) character ( * ), intent ( in ), optional :: delim character (:), allocatable :: cat integer :: i character (:), allocatable :: delim_str if ( size ( strings ) < 1 ) then cat = '' return end if if ( present ( delim )) then delim_str = delim else delim_str = '' end if cat = strings ( 1 )% s do i = 2 , size ( strings ) cat = cat // delim_str // strings ( i )% s end do end function string_cat","tags":"","loc":"proc/string_cat.html"},{"title":"to_fortran_name – Fortran-lang/fpm","text":"public pure function to_fortran_name(string) result(res) Returns string with special characters replaced with an underscore.\nFor now, only a hyphen is treated as a special character, but this can be\nexpanded to other characters if needed. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string Return Value character(len=len(string)) Source Code pure function to_fortran_name ( string ) result ( res ) character ( * ), intent ( in ) :: string character ( len ( string )) :: res character , parameter :: SPECIAL_CHARACTERS ( * ) = [ '-' ] res = replace ( string , SPECIAL_CHARACTERS , '_' ) end function to_fortran_name","tags":"","loc":"proc/to_fortran_name.html"},{"title":"upper – Fortran-lang/fpm","text":"public pure elemental function upper(str, begin, end) result(string) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str integer, intent(in), optional :: begin integer, intent(in), optional :: end Return Value character(len=len(str)) Source Code elemental pure function upper ( str , begin , end ) result ( string ) character ( * ), intent ( In ) :: str character ( len ( str )) :: string integer , intent ( in ), optional :: begin , end integer :: i integer :: ibegin , iend string = str ibegin = 1 if ( present ( begin )) then ibegin = max ( ibegin , begin ) endif iend = len_trim ( str ) if ( present ( end )) then iend = min ( iend , end ) endif do i = ibegin , iend ! step thru each letter in the string in specified range select case ( str ( i : i )) case ( 'a' : 'z' ) string ( i : i ) = char ( iachar ( str ( i : i )) - 32 ) ! change letter to capitalized case default end select end do end function upper","tags":"","loc":"proc/upper.html"},{"title":"notabs – Fortran-lang/fpm","text":"public impure elemental subroutine notabs(instr, outstr, ilen) NAME notabs(3f) - [fpm_strings:NONALPHA] expand tab characters\n (LICENSE:PD) SYNOPSIS subroutine notabs(INSTR,OUTSTR,ILEN)\n\n character(len=*),intent=(in) :: INSTR\n character(len=*),intent=(out) :: OUTSTR\n integer,intent=(out) :: ILEN DESCRIPTION NOTABS() converts tabs in INSTR to spaces in OUTSTR while maintaining\n columns. It assumes a tab is set every 8 characters. Trailing spaces\n are removed. In addition, trailing carriage returns and line feeds are removed\n (they are usually a problem created by going to and from MSWindows). What are some reasons for removing tab characters from an input line?\n Some Fortran compilers have problems with tabs, as tabs are not\n part of the Fortran character set. Some editors and printers will\n have problems with tabs. It is often useful to expand tabs in input\n files to simplify further processing such as tokenizing an input line. OPTIONS instr Input line to remove tabs from RESULTS outstr Output string with tabs expanded. Assumed to be of sufficient\n length\n ilen Significant length of returned string EXAMPLES Sample program: program demo_notabs\n\n! test filter to remove tabs and trailing white space from input\n! on files up to 1024 characters wide\nuse fpm_strings, only : notabs\ncharacter(len=1024) :: in,out\ninteger :: ios,iout\n do\n read(*,'(A)',iostat=ios)in\n if(ios /= 0) exit\n call notabs(in,out,iout)\n write(*,'(a)')out(:iout)\n enddo\nend program demo_notabs SEE ALSO GNU/Unix commands expand(1) and unexpand(1) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: instr character(len=*), intent(out) :: outstr integer, intent(out) :: ilen Source Code elemental impure subroutine notabs ( instr , outstr , ilen ) ! ident_31=\"@(#)fpm_strings::notabs(3f): convert tabs to spaces while maintaining columns, remove CRLF chars\" character ( len =* ), intent ( in ) :: instr ! input line to scan for tab characters character ( len =* ), intent ( out ) :: outstr ! tab-expanded version of INSTR produced integer , intent ( out ) :: ilen ! column position of last character put into output string ! that is, ILEN holds the position of the last non-blank character in OUTSTR integer , parameter :: tabsize = 8 ! assume a tab stop is set every 8th column integer :: ipos ! position in OUTSTR to put next character of INSTR integer :: lenin ! length of input string trimmed of trailing spaces integer :: lenout ! number of characters output string can hold integer :: istep ! counter that advances thru input string INSTR one character at a time character ( len = 1 ) :: c ! character in input line being processed integer :: iade ! ADE (ASCII Decimal Equivalent) of character being tested ipos = 1 ! where to put next character in output string OUTSTR lenin = len_trim ( instr ( 1 : len ( instr ) )) ! length of INSTR trimmed of trailing spaces lenout = len ( outstr ) ! number of characters output string OUTSTR can hold outstr = \" \" ! this SHOULD blank-fill string, a buggy machine required a loop to set all characters SCAN_LINE : do istep = 1 , lenin ! look through input string one character at a time c = instr ( istep : istep ) ! get next character iade = ichar ( c ) ! get ADE of the character EXPAND_TABS : select case ( iade ) ! take different actions depending on which character was found case ( 9 ) ! test if character is a tab and move pointer out to appropriate column ipos = ipos + ( tabsize - ( mod ( ipos - 1 , tabsize ))) case ( 10 , 13 ) ! convert carriage-return and new-line to space ,typically to handle DOS-format files ipos = ipos + 1 case default ! c is anything else other than a tab,newline,or return insert it in output string if ( ipos > lenout ) then write ( stderr , * ) \"*notabs* output string overflow\" exit else outstr ( ipos : ipos ) = c ipos = ipos + 1 endif end select EXPAND_TABS enddo SCAN_LINE ipos = min ( ipos , lenout ) ! tabs or newline or return characters or last character might have gone too far ilen = len_trim ( outstr (: ipos )) ! trim trailing spaces end subroutine notabs","tags":"","loc":"proc/notabs.html"},{"title":"remove_characters_in_set – Fortran-lang/fpm","text":"public subroutine remove_characters_in_set(string, set, replace_with) Arguments Type Intent Optional Attributes Name character(len=:), intent(inout), allocatable :: string character(len=*), intent(in) :: set character(len=1), intent(in), optional :: replace_with Source Code subroutine remove_characters_in_set ( string , set , replace_with ) character ( len = :), allocatable , intent ( inout ) :: string character ( * ), intent ( in ) :: set character , optional , intent ( in ) :: replace_with ! Replace with this character instead of removing integer :: feed , length if (. not . allocated ( string )) return if ( len ( set ) <= 0 ) return length = len ( string ) feed = scan ( string , set ) do while ( length > 0 . and . feed > 0 ) ! Remove heading if ( length == 1 ) then string = \"\" elseif ( feed == 1 ) then string = string ( 2 : length ) ! Remove trailing elseif ( feed == length ) then string = string ( 1 : length - 1 ) ! In between: replace with given character elseif ( present ( replace_with )) then string ( feed : feed ) = replace_with ! Or just remove else string = string ( 1 : feed - 1 ) // string ( feed + 1 : length ) end if length = len ( string ) feed = scan ( string , set ) end do end subroutine remove_characters_in_set","tags":"","loc":"proc/remove_characters_in_set.html"},{"title":"remove_newline_characters – Fortran-lang/fpm","text":"public subroutine remove_newline_characters(string) Arguments Type Intent Optional Attributes Name type( string_t ), intent(inout) :: string Source Code subroutine remove_newline_characters ( string ) type ( string_t ), intent ( inout ) :: string integer :: feed , length character ( * ), parameter :: CRLF = achar ( 13 ) // new_line ( 'a' ) character ( * ), parameter :: SPACE = ' ' call remove_characters_in_set ( string % s , set = CRLF , replace_with = SPACE ) end subroutine remove_newline_characters","tags":"","loc":"proc/remove_newline_characters.html"},{"title":"split – Fortran-lang/fpm","text":"public subroutine split(input_line, array, delimiters, order, nulls) parse string on delimiter characters and store tokens into an allocatable array\ngiven a line of structure ” par1 par2 par3 … parn ” store each par(n) into a separate variable in array. by default adjacent delimiters in the input string do not create an empty string in the output array no quoting of delimiters is supported Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: input_line input string to tokenize character(len=:), intent(out), allocatable :: array (:) output array of tokens character(len=*), intent(in), optional :: delimiters list of delimiter characters character(len=*), intent(in), optional :: order order of output array sequential|[reverse|right] character(len=*), intent(in), optional :: nulls return strings composed of delimiters or not ignore|return|ignoreend Source Code subroutine split ( input_line , array , delimiters , order , nulls ) !! given a line of structure \" par1 par2 par3 ... parn \" store each par(n) into a separate variable in array. !! !! * by default adjacent delimiters in the input string do not create an empty string in the output array !! * no quoting of delimiters is supported character ( len =* ), intent ( in ) :: input_line !! input string to tokenize character ( len =* ), optional , intent ( in ) :: delimiters !! list of delimiter characters character ( len =* ), optional , intent ( in ) :: order !! order of output array sequential|[reverse|right] character ( len =* ), optional , intent ( in ) :: nulls !! return strings composed of delimiters or not ignore|return|ignoreend character ( len = :), allocatable , intent ( out ) :: array (:) !! output array of tokens integer :: n ! max number of strings INPUT_LINE could split into if all delimiter integer , allocatable :: ibegin (:) ! positions in input string where tokens start integer , allocatable :: iterm (:) ! positions in input string where tokens end character ( len = :), allocatable :: dlim ! string containing delimiter characters character ( len = :), allocatable :: ordr ! string containing order keyword character ( len = :), allocatable :: nlls ! string containing nulls keyword integer :: ii , iiii ! loop parameters used to control print order integer :: icount ! number of tokens found integer :: ilen ! length of input string with trailing spaces trimmed integer :: i10 , i20 , i30 ! loop counters integer :: icol ! pointer into input string as it is being parsed integer :: idlim ! number of delimiter characters integer :: ifound ! where next delimiter character is found in remaining input string data integer :: inotnull ! count strings not composed of delimiters integer :: ireturn ! number of tokens returned integer :: imax ! length of longest token ! decide on value for optional DELIMITERS parameter if ( present ( delimiters )) then ! optional delimiter list was present if ( delimiters /= '' ) then ! if DELIMITERS was specified and not null use it dlim = delimiters else ! DELIMITERS was specified on call as empty string dlim = ' ' // char ( 9 ) // char ( 10 ) // char ( 11 ) // char ( 12 ) // char ( 13 ) // char ( 0 ) ! use default delimiter when not specified endif else ! no delimiter value was specified dlim = ' ' // char ( 9 ) // char ( 10 ) // char ( 11 ) // char ( 12 ) // char ( 13 ) // char ( 0 ) ! use default delimiter when not specified endif idlim = len ( dlim ) ! dlim a lot of blanks on some machines if dlim is a big string if ( present ( order )) then ; ordr = lower ( adjustl ( order )); else ; ordr = 'sequential' ; endif ! decide on value for optional ORDER parameter if ( present ( nulls )) then ; nlls = lower ( adjustl ( nulls )); else ; nlls = 'ignore' ; endif ! optional parameter n = len ( input_line ) + 1 ! max number of strings INPUT_LINE could split into if all delimiter allocate ( ibegin ( n )) ! allocate enough space to hold starting location of tokens if string all tokens allocate ( iterm ( n )) ! allocate enough space to hold ending location of tokens if string all tokens ibegin (:) = 1 iterm (:) = 1 ilen = len ( input_line ) ! ILEN is the column position of the last non-blank character icount = 0 ! how many tokens found inotnull = 0 ! how many tokens found not composed of delimiters imax = 0 ! length of longest token found select case ( ilen ) case ( 0 ) ! command was totally blank case default ! there is at least one non-delimiter in INPUT_LINE if get here icol = 1 ! initialize pointer into input line INFINITE : do i30 = 1 , ilen , 1 ! store into each array element ibegin ( i30 ) = icol ! assume start new token on the character if ( index ( dlim ( 1 : idlim ), input_line ( icol : icol )) == 0 ) then ! if current character is not a delimiter iterm ( i30 ) = ilen ! initially assume no more tokens do i10 = 1 , idlim ! search for next delimiter ifound = index ( input_line ( ibegin ( i30 ): ilen ), dlim ( i10 : i10 )) IF ( ifound > 0 ) then iterm ( i30 ) = min ( iterm ( i30 ), ifound + ibegin ( i30 ) - 2 ) endif enddo icol = iterm ( i30 ) + 2 ! next place to look as found end of this token inotnull = inotnull + 1 ! increment count of number of tokens not composed of delimiters else ! character is a delimiter for a null string iterm ( i30 ) = icol - 1 ! record assumed end of string. Will be less than beginning icol = icol + 1 ! advance pointer into input string endif imax = max ( imax , iterm ( i30 ) - ibegin ( i30 ) + 1 ) icount = i30 ! increment count of number of tokens found if ( icol > ilen ) then ! no text left exit INFINITE endif enddo INFINITE end select select case ( trim ( adjustl ( nlls ))) case ( 'ignore' , '' , 'ignoreend' ) ireturn = inotnull case default ireturn = icount end select allocate ( character ( len = imax ) :: array ( ireturn )) ! allocate the array to return !allocate(array(ireturn)) ! allocate the array to turn select case ( trim ( adjustl ( ordr ))) ! decide which order to store tokens case ( 'reverse' , 'right' ) ; ii = ireturn ; iiii =- 1 ! last to first case default ; ii = 1 ; iiii = 1 ! first to last end select do i20 = 1 , icount ! fill the array with the tokens that were found if ( iterm ( i20 ) < ibegin ( i20 )) then select case ( trim ( adjustl ( nlls ))) case ( 'ignore' , '' , 'ignoreend' ) case default array ( ii ) = ' ' ii = ii + iiii end select else array ( ii ) = input_line ( ibegin ( i20 ): iterm ( i20 )) ii = ii + iiii endif enddo end subroutine split","tags":"","loc":"proc/split.html"},{"title":"split_first_last – Fortran-lang/fpm","text":"public pure subroutine split_first_last(string, set, first, last) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string character(len=*), intent(in) :: set integer, intent(out), allocatable :: first (:) integer, intent(out), allocatable :: last (:) Source Code pure subroutine split_first_last ( string , set , first , last ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: set integer , allocatable , intent ( out ) :: first (:) integer , allocatable , intent ( out ) :: last (:) integer , dimension ( len ( string ) + 1 ) :: istart , iend integer :: p , n , slen slen = len ( string ) n = 0 if ( slen > 0 ) then p = 0 do while ( p < slen ) n = n + 1 istart ( n ) = min ( p + 1 , slen ) call split_pos ( string , set , p ) iend ( n ) = p - 1 end do end if first = istart (: n ) last = iend (: n ) end subroutine split_first_last","tags":"","loc":"proc/split_first_last.html"},{"title":"fnv_1a – Fortran-lang/fpm","text":"public interface fnv_1a Module Procedures private pure function fnv_1a_char(input, seed) result(hash) Hash a character(*) string of default kind Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: input integer(kind=int64), intent(in), optional :: seed Return Value integer(kind=int64) private pure function fnv_1a_string_t(input, seed) result(hash) Hash a string_t array of default kind Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: input (:) integer(kind=int64), intent(in), optional :: seed Return Value integer(kind=int64)","tags":"","loc":"interface/fnv_1a.html"},{"title":"len_trim – Fortran-lang/fpm","text":"public interface len_trim Module Procedures private elemental function string_len_trim(string) result(n) Determine total trimmed length of string_t array Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: string Return Value integer private pure function strings_len_trim(strings) result(n) Determine total trimmed length of string_t array Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: strings (:) Return Value integer","tags":"","loc":"interface/len_trim.html"},{"title":"operator(.in.) – Fortran-lang/fpm","text":"public interface operator(.in.) Module Procedures public function string_array_contains (search_string, array) Check if array of TYPE(STRING_T) matches a particular CHARACTER string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: search_string type( string_t ), intent(in) :: array (:) Return Value logical","tags":"","loc":"interface/operator(.in.).html"},{"title":"operator(==) – Fortran-lang/fpm","text":"public interface operator(==) Module Procedures private pure function string_is_same(this, that) Check that two string objects are exactly identical Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: this two strings to be compared type( string_t ), intent(in) :: that two strings to be compared Return Value logical private pure function string_arrays_same(this, that) Check that two allocatable string object arrays are exactly identical Arguments Type Intent Optional Attributes Name type( string_t ), intent(in), allocatable :: this (:) two string arrays to be compared type( string_t ), intent(in), allocatable :: that (:) two string arrays to be compared Return Value logical","tags":"","loc":"interface/operator(==).html"},{"title":"resize – Fortran-lang/fpm","text":"public interface resize Module Procedures private subroutine resize_string(list, n) increase the size of a TYPE(STRING_T) array by N elements Arguments Type Intent Optional Attributes Name type( string_t ), intent(inout), allocatable :: list (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size","tags":"","loc":"interface/resize.html"},{"title":"str – Fortran-lang/fpm","text":"public interface str Module Procedures private pure function str_int(i) result(s) Converts integer “i” to string Arguments Type Intent Optional Attributes Name integer, intent(in) :: i Return Value character(len=str_int_len) private pure function str_int64(i) result(s) Converts integer “i” to string Arguments Type Intent Optional Attributes Name integer(kind=int64), intent(in) :: i Return Value character(len=str_int64_len) private pure function str_logical(l) result(s) Converts logical “l” to string Arguments Type Intent Optional Attributes Name logical, intent(in) :: l Return Value character(len=str_logical_len)","tags":"","loc":"interface/str.html"},{"title":"str_ends_with – Fortran-lang/fpm","text":"public interface str_ends_with Module Procedures private pure function str_ends_with_str(s, e) result(r) test if a CHARACTER string ends with a specified suffix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e Return Value logical private pure function str_ends_with_any(s, e) result(r) test if a CHARACTER string ends with any of an array of suffixs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e (:) Return Value logical private pure function str_ends_with_any_string(s, e) result(r) Test if a CHARACTER string ends with any of an array of string suffixs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s type( string_t ), intent(in) :: e (:) Return Value logical","tags":"","loc":"interface/str_ends_with.html"},{"title":"string_t – Fortran-lang/fpm","text":"public interface string_t Module Procedures private function new_string_t(s) result(string) Helper function to generate a new string_t instance\n (Required due to the allocatable component) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s Return Value type( string_t )","tags":"","loc":"interface/string_t.html"},{"title":"assert_pkg_config – Fortran-lang/fpm","text":"public function assert_pkg_config() Check whether pkg-config is available on the local system Arguments None Return Value logical Source Code logical function assert_pkg_config () integer :: exitcode logical :: success type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), args = [ string_t ( '-h' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) assert_pkg_config = exitcode == 0 . and . success end function assert_pkg_config","tags":"","loc":"proc/assert_pkg_config.html"},{"title":"pkgcfg_get_build_flags – Fortran-lang/fpm","text":"public function pkgcfg_get_build_flags(name, allow_system, error) result(flags) Get build flags (option to include flags from system directories, that \ngfortran does not look into by default) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Package name logical, intent(in) :: allow_system Should pkg-config look in system paths? This is necessary for gfortran \nthat doesn’t otherwise look into them type( error_t ), intent(out), allocatable :: error Error flag Return Value type( string_t ), allocatable, (:) List of compile flags Source Code function pkgcfg_get_build_flags ( name , allow_system , error ) result ( flags ) !> Package name character ( * ), intent ( in ) :: name !> Should pkg-config look in system paths? This is necessary for gfortran !> that doesn't otherwise look into them logical , intent ( in ) :: allow_system !> Error flag type ( error_t ), allocatable , intent ( out ) :: error !> List of compile flags type ( string_t ), allocatable :: flags (:) integer :: exitcode , i , nlib logical :: old_had , success , old_allow character (:), allocatable :: old , tokens (:) type ( string_t ) :: log ! Check if the current environment includes system flags old = get_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , default = 'ERROR' ) old_had = old /= 'ERROR' old_allow = merge ( old == '1' ,. false ., old_had ) ! Set system flags success = set_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , value = merge ( '1' , '0' , allow_system )) if (. not . success ) then call fatal_error ( error , 'Cannot get pkg-config build flags: environment variable error.' ) return end if ! Now run wrapper call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( name ), string_t ( '--cflags' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) ! Split all arguments tokens = shlex_split ( log % s ) nlib = size ( tokens ) allocate ( flags ( nlib )) do i = 1 , nlib flags ( i ) = string_t ( trim ( adjustl ( tokens ( i )))) end do else allocate ( flags ( 0 )) call fatal_error ( error , 'cannot get <' // name // '> build flags from pkg-config' ) end if ! Restore environment variable if ( old_had ) then success = set_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , value = old ) else success = delete_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' ) end if if (. not . success ) then call fatal_error ( error , 'Cannot get pkg-config build flags: environment variable error.' ) return end if end function pkgcfg_get_build_flags","tags":"","loc":"proc/pkgcfg_get_build_flags.html"},{"title":"pkgcfg_get_libs – Fortran-lang/fpm","text":"public function pkgcfg_get_libs(package, error) result(libraries) Get package libraries from pkg-config Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: package Package name type( error_t ), intent(out), allocatable :: error Error handler Return Value type( string_t ), allocatable, (:) A list of libraries Source Code function pkgcfg_get_libs ( package , error ) result ( libraries ) !> Package name character ( * ), intent ( in ) :: package !> Error handler type ( error_t ), allocatable , intent ( out ) :: error !> A list of libraries type ( string_t ), allocatable :: libraries (:) integer :: exitcode , nlib , i logical :: success character ( len = :), allocatable :: tokens (:) type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( package ), string_t ( '--libs' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) ! Split all arguments tokens = shlex_split ( log % s ) nlib = size ( tokens ) allocate ( libraries ( nlib )) do i = 1 , nlib libraries ( i ) = string_t ( trim ( adjustl ( tokens ( i )))) end do else allocate ( libraries ( 0 )) call fatal_error ( error , 'cannot get <' // package // '> libraries from pkg-config' ) end if end function pkgcfg_get_libs","tags":"","loc":"proc/pkgcfg_get_libs.html"},{"title":"pkgcfg_get_version – Fortran-lang/fpm","text":"public function pkgcfg_get_version(package, error) result(screen) Get package version from pkg-config Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: package Package name type( error_t ), intent(out), allocatable :: error Error handler Return Value type( string_t ) Source Code type ( string_t ) function pkgcfg_get_version ( package , error ) result ( screen ) !> Package name character ( * ), intent ( in ) :: package !> Error handler type ( error_t ), allocatable , intent ( out ) :: error integer :: exitcode logical :: success type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( package ), string_t ( '--modversion' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) screen = log else screen = string_t ( \"\" ) end if end function pkgcfg_get_version","tags":"","loc":"proc/pkgcfg_get_version.html"},{"title":"pkgcfg_has_package – Fortran-lang/fpm","text":"public function pkgcfg_has_package(name) result(success) Check if pkgcfg has package pkg-config –exists returns 0 only if the package exists Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Package name Return Value logical Source Code logical function pkgcfg_has_package ( name ) result ( success ) !> Package name character ( * ), intent ( in ) :: name integer :: exitcode logical :: cmdok type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( name ), string_t ( '--exists' )], & exitcode = exitcode , cmd_success = cmdok , screen_output = log ) !> pkg-config --exists returns 0 only if the package exists success = cmdok . and . exitcode == 0 end function pkgcfg_has_package","tags":"","loc":"proc/pkgcfg_has_package.html"},{"title":"pkgcfg_list_all – Fortran-lang/fpm","text":"public function pkgcfg_list_all(error, descriptions) result(modules) Return whole list of available pkg-cfg packages Extract list Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Error handler type( string_t ), intent(out), optional, allocatable :: descriptions (:) An optional list of package descriptions Return Value type( string_t ), allocatable, (:) A list of all available packages Source Code function pkgcfg_list_all ( error , descriptions ) result ( modules ) !> Error handler type ( error_t ), allocatable , intent ( out ) :: error !> A list of all available packages type ( string_t ), allocatable :: modules (:) !> An optional list of package descriptions type ( string_t ), optional , allocatable , intent ( out ) :: descriptions (:) integer :: exitcode , i , spc logical :: success character ( len = :), allocatable :: lines (:) type ( string_t ) :: log type ( string_t ), allocatable :: mods (:), descr (:) character ( * ), parameter :: CRLF = achar ( 13 ) // new_line ( 'a' ) call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( '--list-all' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if (. not .( success . and . exitcode == 0 )) then call fatal_error ( error , 'cannot get pkg-config modules' ) allocate ( modules ( 0 )) return end if !> Extract list call split ( log % s , lines , CRLF ) allocate ( mods ( size ( lines )), descr ( size ( lines ))) do i = 1 , size ( lines ) ! Module names have no spaces spc = index ( lines ( i ), ' ' ) if ( spc > 0 ) then mods ( i ) = string_t ( trim ( adjustl ( lines ( i )( 1 : spc )))) descr ( i ) = string_t ( trim ( adjustl ( lines ( i )( spc + 1 :)))) else mods ( i ) = string_t ( trim ( adjustl ( lines ( i )))) descr ( i ) = string_t ( \"\" ) end if end do call move_alloc ( from = mods , to = modules ) if ( present ( descriptions )) call move_alloc ( from = descr , to = descriptions ) end function pkgcfg_list_all","tags":"","loc":"proc/pkgcfg_list_all.html"},{"title":"run_wrapper – Fortran-lang/fpm","text":"public subroutine run_wrapper(wrapper, args, verbose, exitcode, cmd_success, screen_output) Simple call to execute_command_line involving one mpi* wrapper Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: wrapper type( string_t ), intent(in), optional :: args (:) logical, intent(in), optional :: verbose integer, intent(out), optional :: exitcode logical, intent(out), optional :: cmd_success type( string_t ), intent(out), optional :: screen_output Source Code subroutine run_wrapper ( wrapper , args , verbose , exitcode , cmd_success , screen_output ) type ( string_t ), intent ( in ) :: wrapper type ( string_t ), intent ( in ), optional :: args (:) logical , intent ( in ), optional :: verbose integer , intent ( out ), optional :: exitcode logical , intent ( out ), optional :: cmd_success type ( string_t ), intent ( out ), optional :: screen_output logical :: echo_local character (:), allocatable :: redirect_str , command , redirect , line integer :: iunit , iarg , stat , cmdstat if ( present ( verbose )) then echo_local = verbose else echo_local = . false . end if ! No redirection and non-verbose output if ( present ( screen_output )) then redirect = get_temp_filename () redirect_str = \">\" // redirect // \" 2>&1\" else if ( os_is_unix ()) then redirect_str = \" >/dev/null 2>&1\" else redirect_str = \" >NUL 2>&1\" end if end if ! Empty command if ( len_trim ( wrapper ) <= 0 ) then if ( echo_local ) print * , '+ ' if ( present ( exitcode )) exitcode = 0 if ( present ( cmd_success )) cmd_success = . true . if ( present ( screen_output )) screen_output = string_t ( \"\" ) return end if ! Init command command = trim ( wrapper % s ) add_arguments : if ( present ( args )) then do iarg = 1 , size ( args ) if ( len_trim ( args ( iarg )) <= 0 ) cycle command = trim ( command ) // ' ' // args ( iarg )% s end do endif add_arguments if ( echo_local ) print * , '+ ' , command ! Test command call execute_command_line ( command // redirect_str , exitstat = stat , cmdstat = cmdstat ) ! Command successful? if ( present ( cmd_success )) cmd_success = cmdstat == 0 ! Program exit code? if ( present ( exitcode )) exitcode = stat ! Want screen output? if ( present ( screen_output ) . and . cmdstat == 0 ) then allocate ( character ( len = 0 ) :: screen_output % s ) open ( newunit = iunit , file = redirect , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit screen_output % s = screen_output % s // new_line ( 'a' ) // line if ( echo_local ) write ( * , '(A)' ) trim ( line ) end do ! Close and delete file close ( iunit , status = 'delete' ) else call fpm_stop ( 1 , 'cannot read temporary file from successful MPI wrapper' ) endif end if end subroutine run_wrapper","tags":"","loc":"proc/run_wrapper.html"},{"title":"has_manifest – Fortran-lang/fpm","text":"function has_manifest(dir) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir Return Value logical Source Code function has_manifest ( dir ) character ( len =* ), intent ( in ) :: dir logical :: has_manifest has_manifest = exists ( join_path ( dir , \"fpm.toml\" )) end function has_manifest","tags":"","loc":"proc/has_manifest.html"},{"title":"get_working_dir – Fortran-lang/fpm","text":"subroutine get_working_dir(settings, working_dir_) Save access to working directory in settings, in case setting have not been allocated Arguments Type Intent Optional Attributes Name class( fpm_cmd_settings ), intent(in), optional :: settings character(len=:), intent(out), allocatable :: working_dir_ Source Code subroutine get_working_dir ( settings , working_dir_ ) class ( fpm_cmd_settings ), optional , intent ( in ) :: settings character ( len = :), allocatable , intent ( out ) :: working_dir_ if ( present ( settings )) then working_dir_ = settings % working_dir end if end subroutine get_working_dir","tags":"","loc":"proc/get_working_dir.html"},{"title":"handle_error – Fortran-lang/fpm","text":"subroutine handle_error(error_) Arguments Type Intent Optional Attributes Name type( error_t ), intent(in), optional :: error_ Source Code subroutine handle_error ( error_ ) type ( error_t ), optional , intent ( in ) :: error_ if ( present ( error_ )) then write ( error_unit , '(\"[Error]\", 1x, a)' ) error_ % message stop 1 end if end subroutine handle_error","tags":"","loc":"proc/handle_error~2.html"},{"title":"MPI_TYPE_NAME – Fortran-lang/fpm","text":"public pure function MPI_TYPE_NAME(mpilib) result(name) Return a name for the MPI library Arguments Type Intent Optional Attributes Name integer, intent(in) :: mpilib Return Value character(len=:), allocatable Source Code pure function MPI_TYPE_NAME ( mpilib ) result ( name ) integer , intent ( in ) :: mpilib character ( len = :), allocatable :: name select case ( mpilib ) case ( MPI_TYPE_NONE ); name = \"none\" case ( MPI_TYPE_OPENMPI ); name = \"OpenMPI\" case ( MPI_TYPE_MPICH ); name = \"MPICH\" case ( MPI_TYPE_INTEL ); name = \"INTELMPI\" case ( MPI_TYPE_MSMPI ); name = \"MS-MPI\" case default ; name = \"UNKNOWN\" end select end function MPI_TYPE_NAME","tags":"","loc":"proc/mpi_type_name.html"},{"title":"resolve_metapackages – Fortran-lang/fpm","text":"public interface resolve_metapackages Module Procedures private subroutine resolve_metapackage_model(model, package, settings, error) Resolve all metapackages into the package config Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(inout) :: model type( package_config_t ), intent(inout) :: package class( fpm_build_settings ), intent(inout) :: settings type( error_t ), intent(out), allocatable :: error","tags":"","loc":"interface/resolve_metapackages.html"},{"title":"build_package – Fortran-lang/fpm","text":"public subroutine build_package(targets, model, verbose) Top-level routine to build package described by model Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout) :: targets (:) type( fpm_model_t ), intent(in) :: model logical, intent(in) :: verbose Source Code subroutine build_package ( targets , model , verbose ) type ( build_target_ptr ), intent ( inout ) :: targets (:) type ( fpm_model_t ), intent ( in ) :: model logical , intent ( in ) :: verbose integer :: i , j type ( build_target_ptr ), allocatable :: queue (:) integer , allocatable :: schedule_ptr (:), stat (:) logical :: build_failed , skip_current type ( string_t ), allocatable :: build_dirs (:) type ( string_t ) :: temp type ( build_progress_t ) :: progress logical :: plain_output ! Need to make output directory for include (mod) files allocate ( build_dirs ( 0 )) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( target % output_dir . in . build_dirs ) cycle temp % s = target % output_dir build_dirs = [ build_dirs , temp ] end associate end do do i = 1 , size ( build_dirs ) call mkdir ( build_dirs ( i )% s , verbose ) end do ! Perform depth-first topological sort of targets do i = 1 , size ( targets ) call sort_target ( targets ( i )% ptr ) end do ! Construct build schedule queue call schedule_targets ( queue , schedule_ptr , targets ) ! Check if queue is empty if (. not . verbose . and . size ( queue ) < 1 ) then write ( stderr , '(a)' ) 'Project is up to date' return end if ! Initialise build status flags allocate ( stat ( size ( queue ))) stat (:) = 0 build_failed = . false . ! Set output mode #ifndef FPM_BOOTSTRAP plain_output = (. not .( c_isatty () == 1 )) . or . verbose #else plain_output = . true . #endif progress = build_progress_t ( queue , plain_output ) ! Loop over parallel schedule regions do i = 1 , size ( schedule_ptr ) - 1 ! Build targets in schedule region i !$omp parallel do default(shared) private(skip_current) schedule(dynamic,1) do j = schedule_ptr ( i ),( schedule_ptr ( i + 1 ) - 1 ) ! Check if build already failed !$omp atomic read skip_current = build_failed if (. not . skip_current ) then call progress % compiling_status ( j ) call build_target ( model , queue ( j )% ptr , verbose , stat ( j )) call progress % completed_status ( j , stat ( j )) end if ! Set global flag if this target failed to build if ( stat ( j ) /= 0 ) then !$omp atomic write build_failed = . true . end if end do ! Check if this schedule region failed: exit with message if failed if ( build_failed ) then write ( * , * ) do j = 1 , size ( stat ) if ( stat ( j ) /= 0 ) Then call print_build_log ( queue ( j )% ptr ) end if end do do j = 1 , size ( stat ) if ( stat ( j ) /= 0 ) then write ( stderr , '(*(g0:,1x))' ) ' Compilation failed for object \"' , basename ( queue ( j )% ptr % output_file ), '\"' end if end do call fpm_stop ( 1 , 'stopping due to failed compilation' ) end if end do call progress % success () end subroutine build_package","tags":"","loc":"proc/build_package.html"},{"title":"schedule_targets – Fortran-lang/fpm","text":"public subroutine schedule_targets(queue, schedule_ptr, targets) Construct a build schedule from the sorted targets. The schedule is broken into regions, described by schedule_ptr ,\n where targets in each region can be compiled in parallel. Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(out), allocatable :: queue (:) integer, allocatable :: schedule_ptr (:) type( build_target_ptr ), intent(in) :: targets (:) Source Code subroutine schedule_targets ( queue , schedule_ptr , targets ) type ( build_target_ptr ), allocatable , intent ( out ) :: queue (:) integer , allocatable :: schedule_ptr (:) type ( build_target_ptr ), intent ( in ) :: targets (:) integer :: i , j integer :: n_schedule , n_sorted n_schedule = 0 ! Number of schedule regions n_sorted = 0 ! Total number of targets to build do i = 1 , size ( targets ) if ( targets ( i )% ptr % sorted ) then n_sorted = n_sorted + 1 end if n_schedule = max ( n_schedule , targets ( i )% ptr % schedule ) end do allocate ( queue ( n_sorted )) allocate ( schedule_ptr ( n_schedule + 1 )) ! Construct the target queue and schedule region pointer n_sorted = 1 schedule_ptr ( n_sorted ) = 1 do i = 1 , n_schedule do j = 1 , size ( targets ) if ( targets ( j )% ptr % sorted ) then if ( targets ( j )% ptr % schedule == i ) then queue ( n_sorted )% ptr => targets ( j )% ptr n_sorted = n_sorted + 1 end if end if end do schedule_ptr ( i + 1 ) = n_sorted end do end subroutine schedule_targets","tags":"","loc":"proc/schedule_targets.html"},{"title":"sort_target – Fortran-lang/fpm","text":"public recursive subroutine sort_target(target) Topologically sort a target for scheduling by\n recursing over its dependencies. Checks disk-cached source hashes to determine if objects are\n up-to-date. Up-to-date sources are tagged as skipped. On completion, target should either be marked as\nsorted ( target%sorted=.true. ) or skipped ( target%skip=.true. ) If target is marked as sorted, target%schedule should be an\ninteger greater than zero indicating the region for scheduling Arguments Type Intent Optional Attributes Name type( build_target_t ), intent(inout), target :: target Source Code recursive subroutine sort_target ( target ) type ( build_target_t ), intent ( inout ), target :: target integer :: i , fh , stat ! Check if target has already been processed (as a dependency) if ( target % sorted . or . target % skip ) then return end if ! Check for a circular dependency ! (If target has been touched but not processed) if ( target % touched ) then call fpm_stop ( 1 , '(!) Circular dependency found with: ' // target % output_file ) else target % touched = . true . ! Set touched flag end if ! Load cached source file digest if present if (. not . allocated ( target % digest_cached ) . and . & exists ( target % output_file ) . and . & exists ( target % output_file // '.digest' )) then allocate ( target % digest_cached ) open ( newunit = fh , file = target % output_file // '.digest' , status = 'old' ) read ( fh , * , iostat = stat ) target % digest_cached close ( fh ) if ( stat /= 0 ) then ! Cached digest is not recognized deallocate ( target % digest_cached ) end if end if if ( allocated ( target % source )) then ! Skip if target is source-based and source file is unmodified if ( allocated ( target % digest_cached )) then if ( target % digest_cached == target % source % digest ) target % skip = . true . end if elseif ( exists ( target % output_file )) then ! Skip if target is not source-based and already exists target % skip = . true . end if ! Loop over target dependencies target % schedule = 1 do i = 1 , size ( target % dependencies ) ! Sort dependency call sort_target ( target % dependencies ( i )% ptr ) if (. not . target % dependencies ( i )% ptr % skip ) then ! Can't skip target if any dependency is not skipped target % skip = . false . ! Set target schedule after all of its dependencies target % schedule = max ( target % schedule , target % dependencies ( i )% ptr % schedule + 1 ) end if end do ! Mark flag as processed: either sorted or skipped target % sorted = . not . target % skip end subroutine sort_target","tags":"","loc":"proc/sort_target.html"},{"title":"descriptor_name – Fortran-lang/fpm","text":"public pure function descriptor_name(descriptor) result(name) Code git descriptor to a string Arguments Type Intent Optional Attributes Name integer, intent(in) :: descriptor Return Value character(len=:), allocatable Source Code pure function descriptor_name ( descriptor ) result ( name ) integer , intent ( in ) :: descriptor character ( len = :), allocatable :: name select case ( descriptor ) case ( git_descriptor % default ); name = \"default\" case ( git_descriptor % branch ); name = \"branch\" case ( git_descriptor % tag ); name = \"tag\" case ( git_descriptor % revision ); name = \"revision\" case default ; name = \"ERROR\" end select end function descriptor_name","tags":"","loc":"proc/descriptor_name.html"},{"title":"git_is_same – Fortran-lang/fpm","text":"public function git_is_same(this, that) Check that two git targets are equal\nAll checks passed! Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Source Code logical function git_is_same ( this , that ) class ( git_target_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that git_is_same = . false . select type ( other => that ) type is ( git_target_t ) if (. not .( this % descriptor == other % descriptor )) return if (. not .( this % url == other % url )) return if (. not .( this % object == other % object )) return class default ! Not the same type return end select !> All checks passed! git_is_same = . true . end function git_is_same","tags":"","loc":"proc/git_is_same.html"},{"title":"git_matches_manifest – Fortran-lang/fpm","text":"public function git_matches_manifest(cached, manifest, verbosity, iunit) Check that a cached dependency matches a manifest request The manifest dependency only contains partial information (what’s requested),\nwhile the cached dependency always stores a commit hash because it’s built\nafter the repo is available (saved as git_descriptor%revision==revision).\nSo, comparing against the descriptor is not reliable Arguments Type Intent Optional Attributes Name type( git_target_t ), intent(in) :: cached Two input git targets type( git_target_t ), intent(in) :: manifest Two input git targets integer, intent(in) :: verbosity integer, intent(in) :: iunit Return Value logical Source Code logical function git_matches_manifest ( cached , manifest , verbosity , iunit ) !> Two input git targets type ( git_target_t ), intent ( in ) :: cached , manifest integer , intent ( in ) :: verbosity , iunit git_matches_manifest = cached % url == manifest % url if (. not . git_matches_manifest ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT URL has changed: \" , cached % url , \" vs. \" , manifest % url return endif !> The manifest dependency only contains partial information (what's requested), !> while the cached dependency always stores a commit hash because it's built !> after the repo is available (saved as git_descriptor%revision==revision). !> So, comparing against the descriptor is not reliable git_matches_manifest = allocated ( cached % object ) . eqv . allocated ( manifest % object ) if ( git_matches_manifest . and . allocated ( cached % object )) & git_matches_manifest = cached % object == manifest % object if (. not . git_matches_manifest ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT OBJECT has changed: \" , cached % object , \" vs. \" , manifest % object end if end function git_matches_manifest","tags":"","loc":"proc/git_matches_manifest.html"},{"title":"git_target_branch – Fortran-lang/fpm","text":"public function git_target_branch(url, branch) result(self) Target a branch in the git repository Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: branch Name of the branch of interest Return Value type( git_target_t ) New git target Source Code function git_target_branch ( url , branch ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Name of the branch of interest character ( len =* ), intent ( in ) :: branch !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % branch self % url = url self % object = branch end function git_target_branch","tags":"","loc":"proc/git_target_branch.html"},{"title":"git_target_default – Fortran-lang/fpm","text":"public function git_target_default(url) result(self) Default target Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository Return Value type( git_target_t ) New git target Source Code function git_target_default ( url ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % default self % url = url end function git_target_default","tags":"","loc":"proc/git_target_default.html"},{"title":"git_target_revision – Fortran-lang/fpm","text":"public function git_target_revision(url, sha1) result(self) Target a specific git revision Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: sha1 Commit hash of interest Return Value type( git_target_t ) New git target Source Code function git_target_revision ( url , sha1 ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Commit hash of interest character ( len =* ), intent ( in ) :: sha1 !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % revision self % url = url self % object = sha1 end function git_target_revision","tags":"","loc":"proc/git_target_revision.html"},{"title":"git_target_tag – Fortran-lang/fpm","text":"public function git_target_tag(url, tag) result(self) Target a git tag Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: tag Tag name of interest Return Value type( git_target_t ) New git target Source Code function git_target_tag ( url , tag ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Tag name of interest character ( len =* ), intent ( in ) :: tag !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % tag self % url = url self % object = tag end function git_target_tag","tags":"","loc":"proc/git_target_tag.html"},{"title":"parse_descriptor – Fortran-lang/fpm","text":"public pure function parse_descriptor(name) Parse git descriptor identifier from a string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Return Value integer Source Code pure integer function parse_descriptor ( name ) character ( len =* ), intent ( in ) :: name select case ( name ) case ( \"default\" ); parse_descriptor = git_descriptor % default case ( \"branch\" ); parse_descriptor = git_descriptor % branch case ( \"tag\" ); parse_descriptor = git_descriptor % tag case ( \"revision\" ); parse_descriptor = git_descriptor % revision case default ; parse_descriptor = git_descriptor % error end select end function parse_descriptor","tags":"","loc":"proc/parse_descriptor.html"},{"title":"checkout – Fortran-lang/fpm","text":"public subroutine checkout(self, local_path, error) Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target character(len=*), intent(in) :: local_path Local path to checkout in type( error_t ), intent(out), allocatable :: error Error Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: object integer, public :: stat character(len=:), public, allocatable :: workdir Source Code subroutine checkout ( self , local_path , error ) !> Instance of the git target class ( git_target_t ), intent ( in ) :: self !> Local path to checkout in character ( * ), intent ( in ) :: local_path !> Error type ( error_t ), allocatable , intent ( out ) :: error integer :: stat character ( len = :), allocatable :: object , workdir if ( allocated ( self % object )) then object = self % object else object = 'HEAD' end if workdir = \"--work-tree=\" // local_path // \" --git-dir=\" // join_path ( local_path , \".git\" ) call execute_command_line ( \"git init \" // local_path , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while initiating git repository for remote dependency' ) return end if call execute_command_line ( \"git \" // workdir // \" fetch --depth=1 \" // & self % url // \" \" // object , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while fetching git repository for remote dependency' ) return end if call execute_command_line ( \"git \" // workdir // \" checkout -qf FETCH_HEAD\" , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while checking out git repository for remote dependency' ) return end if end subroutine checkout","tags":"","loc":"proc/checkout.html"},{"title":"dump_to_toml – Fortran-lang/fpm","text":"public subroutine dump_to_toml(self, table, error) Dump dependency to toml table Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ierr Source Code subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( git_target_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_string ( table , \"descriptor\" , descriptor_name ( self % descriptor ), error , 'git_target_t' ) if ( allocated ( error )) return call set_string ( table , \"url\" , self % url , error , 'git_target_t' ) if ( allocated ( error )) return call set_string ( table , \"object\" , self % object , error , 'git_target_t' ) if ( allocated ( error )) return end subroutine dump_to_toml","tags":"","loc":"proc/dump_to_toml~3.html"},{"title":"git_archive – Fortran-lang/fpm","text":"public subroutine git_archive(source, destination, ref, additional_files, verbose, error) Archive a folder using git archive . Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: source Directory to archive. character(len=*), intent(in) :: destination Destination of the archive. character(len=*), intent(in) :: ref (Symbolic) Reference to be archived. character(len=*), intent(in), optional :: additional_files (:) (Optional) list of additional untracked files to be added to the archive. logical, intent(in) :: verbose Print additional information if true. type( error_t ), intent(out), allocatable :: error Error handling. Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: add_files character(len=:), public, allocatable :: archive_format character(len=:), public, allocatable :: cmd_output integer, public :: i integer, public :: stat","tags":"","loc":"proc/git_archive.html"},{"title":"git_revision – Fortran-lang/fpm","text":"public subroutine git_revision(local_path, object, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: local_path Local path to checkout in character(len=:), intent(out), allocatable :: object Git object reference type( error_t ), intent(out), allocatable :: error Error Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: hexdigits = '0123456789abcdef' integer, public :: iend character(len=:), public, allocatable :: iomsg integer, public :: istart character(len=:), public, allocatable :: line integer, public :: stat character(len=:), public, allocatable :: temp_file integer, public :: unit character(len=:), public, allocatable :: workdir Source Code subroutine git_revision ( local_path , object , error ) !> Local path to checkout in character ( * ), intent ( in ) :: local_path !> Git object reference character ( len = :), allocatable , intent ( out ) :: object !> Error type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , unit , istart , iend character ( len = :), allocatable :: temp_file , line , iomsg , workdir character ( len =* ), parameter :: hexdigits = '0123456789abcdef' workdir = \"--work-tree=\" // local_path // \" --git-dir=\" // join_path ( local_path , \".git\" ) allocate ( temp_file , source = get_temp_filename ()) line = \"git \" // workdir // \" log -n 1 > \" // temp_file call execute_command_line ( line , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error while retrieving commit information\" ) return end if open ( file = temp_file , newunit = unit ) call getline ( unit , line , stat , iomsg ) if ( stat /= 0 ) then call fatal_error ( error , iomsg ) return end if close ( unit , status = \"delete\" ) ! Tokenize: ! commit 0123456789abcdef (HEAD, ...) istart = scan ( line , ' ' ) + 1 iend = verify ( line ( istart :), hexdigits ) + istart - 1 if ( iend < istart ) iend = len ( line ) object = line ( istart : iend ) end subroutine git_revision","tags":"","loc":"proc/git_revision.html"},{"title":"info – Fortran-lang/fpm","text":"public subroutine info(self, unit, verbosity) Show information on git target Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: fmt = '(\"#\", 1x, a, t30, a)' integer, public :: pr Source Code subroutine info ( self , unit , verbosity ) !> Instance of the git target class ( git_target_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Git target\" if ( allocated ( self % url )) then write ( unit , fmt ) \"- URL\" , self % url end if if ( allocated ( self % object )) then select case ( self % descriptor ) case default write ( unit , fmt ) \"- object\" , self % object case ( git_descriptor % tag ) write ( unit , fmt ) \"- tag\" , self % object case ( git_descriptor % branch ) write ( unit , fmt ) \"- branch\" , self % object case ( git_descriptor % revision ) write ( unit , fmt ) \"- sha1\" , self % object end select end if end subroutine info","tags":"","loc":"proc/info~3.html"},{"title":"load_from_toml – Fortran-lang/fpm","text":"public subroutine load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Target URL of the git repository Additional descriptor of the git object Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: descriptor_name Local variables Source Code subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( git_target_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: descriptor_name call get_value ( table , \"descriptor\" , descriptor_name ) self % descriptor = parse_descriptor ( descriptor_name ) if ( self % descriptor == git_descriptor % error ) then call fatal_error ( error , \"invalid descriptor ID <\" // descriptor_name // \"> in TOML entry\" ) return end if !> Target URL of the git repository call get_value ( table , \"url\" , self % url ) !> Additional descriptor of the git object call get_value ( table , \"object\" , self % object ) end subroutine load_from_toml","tags":"","loc":"proc/load_from_toml~3.html"},{"title":"manifest_has_changed – Fortran-lang/fpm","text":"public function manifest_has_changed(cached, manifest, verbosity, iunit) result(has_changed) Check if two dependency configurations are different Perform all checks\nAll checks passed! The two instances are equal Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(in) :: cached Two instances of the dependency configuration class( dependency_config_t ), intent(in) :: manifest Two instances of the dependency configuration integer, intent(in) :: verbosity Log verbosity integer, intent(in) :: iunit Log verbosity Return Value logical Source Code logical function manifest_has_changed ( cached , manifest , verbosity , iunit ) result ( has_changed ) !> Two instances of the dependency configuration class ( dependency_config_t ), intent ( in ) :: cached , manifest !> Log verbosity integer , intent ( in ) :: verbosity , iunit has_changed = . true . !> Perform all checks if ( allocated ( cached % git ). neqv . allocated ( manifest % git )) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT presence has changed. \" return endif if ( allocated ( cached % git )) then if (. not . git_matches_manifest ( cached % git , manifest % git , verbosity , iunit )) return end if !> All checks passed! The two instances are equal has_changed = . false . end function manifest_has_changed","tags":"","loc":"proc/manifest_has_changed.html"},{"title":"dependency_destroy – Fortran-lang/fpm","text":"public elemental subroutine dependency_destroy(self) Clean memory Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(inout) :: self Source Code elemental subroutine dependency_destroy ( self ) class ( dependency_config_t ), intent ( inout ) :: self if ( allocated ( self % name )) deallocate ( self % name ) if ( allocated ( self % path )) deallocate ( self % path ) if ( allocated ( self % namespace )) deallocate ( self % namespace ) if ( allocated ( self % requested_version )) deallocate ( self % requested_version ) if ( allocated ( self % git )) deallocate ( self % git ) end subroutine dependency_destroy","tags":"","loc":"proc/dependency_destroy.html"},{"title":"new_dependencies – Fortran-lang/fpm","text":"public subroutine new_dependencies(deps, table, root, meta, error) Construct new dependency array from a TOML data structure Flag dependencies that should be treated as metapackages\nParse all meta- and non-metapackage dependencies Neither a standard dep nor a metapackage\nValid meta dependency Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(out), allocatable :: deps (:) Instance of the dependency configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( metapackage_config_t ), intent(out), optional :: meta (optional) metapackages type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_dependencies ( deps , table , root , meta , error ) !> Instance of the dependency configuration type ( dependency_config_t ), allocatable , intent ( out ) :: deps (:) !> (optional) metapackages type ( metapackage_config_t ), optional , intent ( out ) :: meta !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( * ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: node type ( toml_key ), allocatable :: list (:) type ( dependency_config_t ), allocatable :: all_deps (:) type ( metapackage_request_t ) :: meta_request logical , allocatable :: is_meta (:) logical :: metapackages_allowed integer :: idep , stat , ndep call table % get_keys ( list ) ! An empty table is okay if ( size ( list ) < 1 ) return !> Flag dependencies that should be treated as metapackages metapackages_allowed = present ( meta ) allocate ( is_meta ( size ( list )), source = . false .) allocate ( all_deps ( size ( list ))) !> Parse all meta- and non-metapackage dependencies do idep = 1 , size ( list ) ! Check if this is a standard dependency node call get_value ( table , list ( idep )% key , node , stat = stat ) is_standard_dependency : if ( stat /= toml_stat % success ) then ! See if it can be a valid metapackage name call new_meta_request ( meta_request , list ( idep )% key , table , error = error ) !> Neither a standard dep nor a metapackage if ( allocated ( error )) then call syntax_error ( error , \"Dependency \" // list ( idep )% key // \" is not a valid metapackage or a table entry\" ) return endif !> Valid meta dependency is_meta ( idep ) = . true . else ! Parse as a standard dependency is_meta ( idep ) = . false . call new_dependency ( all_deps ( idep ), node , root , error ) if ( allocated ( error )) return end if is_standard_dependency end do ! Non-meta dependencies ndep = count (. not . is_meta ) ! Finalize standard dependencies allocate ( deps ( ndep )) ndep = 0 do idep = 1 , size ( list ) if ( is_meta ( idep )) cycle ndep = ndep + 1 deps ( ndep ) = all_deps ( idep ) end do ! Finalize meta dependencies if ( metapackages_allowed ) call new_meta_config ( meta , table , is_meta , error ) end subroutine new_dependencies","tags":"","loc":"proc/new_dependencies.html"},{"title":"new_dependency – Fortran-lang/fpm","text":"public subroutine new_dependency(self, table, root, error) Construct a new dependency configuration from a TOML data structure Get optional preprocessor directives Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(out) :: self Instance of the dependency configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_dependency ( self , table , root , error ) !> Instance of the dependency configuration type ( dependency_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( * ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: uri , value , requested_version type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call table % get_key ( self % name ) call get_value ( table , \"namespace\" , self % namespace ) call get_value ( table , \"v\" , requested_version ) if ( allocated ( requested_version )) then if (. not . allocated ( self % requested_version )) allocate ( self % requested_version ) call new_version ( self % requested_version , requested_version , error ) if ( allocated ( error )) return end if !> Get optional preprocessor directives call get_value ( table , \"preprocess\" , child , requested = . false .) if ( associated ( child )) then call new_preprocessors ( self % preprocess , child , error ) if ( allocated ( error )) return endif call get_value ( table , \"path\" , uri ) if ( allocated ( uri )) then if ( get_os_type () == OS_WINDOWS ) uri = windows_path ( uri ) if ( present ( root )) uri = join_path ( root , uri ) ! Relative to the fpm.toml it’s written in call move_alloc ( uri , self % path ) return end if call get_value ( table , \"git\" , uri ) if ( allocated ( uri )) then call get_value ( table , \"tag\" , value ) if ( allocated ( value )) then self % git = git_target_tag ( uri , value ) end if if (. not . allocated ( self % git )) then call get_value ( table , \"branch\" , value ) if ( allocated ( value )) then self % git = git_target_branch ( uri , value ) end if end if if (. not . allocated ( self % git )) then call get_value ( table , \"rev\" , value ) if ( allocated ( value )) then self % git = git_target_revision ( uri , value ) end if end if if (. not . allocated ( self % git )) then self % git = git_target_default ( uri ) end if return end if end subroutine new_dependency","tags":"","loc":"proc/new_dependency.html"},{"title":"resize – Fortran-lang/fpm","text":"public interface resize Module Procedures private pure subroutine resize_dependency_config(var, n) Reallocate a list of dependencies Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(inout), allocatable :: var (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size","tags":"","loc":"interface/resize~2.html"},{"title":"basename – Fortran-lang/fpm","text":"public function basename(path, suffix) result(base) Extract filename from path with/without suffix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path logical, intent(in), optional :: suffix Return Value character(len=:), allocatable Source Code function basename ( path , suffix ) result ( base ) character ( * ), intent ( In ) :: path logical , intent ( in ), optional :: suffix character (:), allocatable :: base character (:), allocatable :: file_parts (:) logical :: with_suffix if (. not . present ( suffix )) then with_suffix = . true . else with_suffix = suffix end if call split ( path , file_parts , delimiters = '\\/' ) if ( size ( file_parts ) > 0 ) then base = trim ( file_parts ( size ( file_parts ))) else base = '' endif if (. not . with_suffix ) then call split ( base , file_parts , delimiters = '.' ) if ( size ( file_parts ) >= 2 ) then base = trim ( file_parts ( size ( file_parts ) - 1 )) endif endif end function basename","tags":"","loc":"proc/basename.html"},{"title":"canon_path – Fortran-lang/fpm","text":"public function canon_path(path) Canonicalize path for comparison\n* Handles path string redundancies\n* Does not test existence of path To be replaced by realpath/_fullname in stdlib_os FIXME: Lot’s of ugly hacks following here Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function canon_path ( path ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: canon_path character ( len = :), allocatable :: nixpath integer :: istart , iend , nn , last logical :: is_path , absolute nixpath = unix_path ( path ) istart = 0 nn = 0 iend = 0 absolute = nixpath ( 1 : 1 ) == \"/\" if ( absolute ) then canon_path = \"/\" else canon_path = \"\" end if do while ( iend < len ( nixpath )) call next ( nixpath , istart , iend , is_path ) if ( is_path ) then select case ( nixpath ( istart : iend )) case ( \".\" , \"\" ) ! always drop empty paths case ( \"..\" ) if ( nn > 0 ) then last = scan ( canon_path (: len ( canon_path ) - 1 ), \"/\" , back = . true .) canon_path = canon_path (: last ) nn = nn - 1 else if (. not . absolute ) then canon_path = canon_path // nixpath ( istart : iend ) // \"/\" end if end if case default nn = nn + 1 canon_path = canon_path // nixpath ( istart : iend ) // \"/\" end select end if end do if ( len ( canon_path ) == 0 ) canon_path = \".\" if ( len ( canon_path ) > 1 . and . canon_path ( len ( canon_path ):) == \"/\" ) then canon_path = canon_path (: len ( canon_path ) - 1 ) end if contains subroutine next ( string , istart , iend , is_path ) character ( len =* ), intent ( in ) :: string integer , intent ( inout ) :: istart integer , intent ( inout ) :: iend logical , intent ( inout ) :: is_path integer :: ii , nn character :: tok nn = len ( string ) if ( iend >= nn ) then istart = nn iend = nn return end if ii = min ( iend + 1 , nn ) tok = string ( ii : ii ) is_path = tok /= '/' if (. not . is_path ) then is_path = . false . istart = ii iend = ii return end if istart = ii do ii = min ( iend + 1 , nn ), nn tok = string ( ii : ii ) select case ( tok ) case ( '/' ) exit case default iend = ii cycle end select end do end subroutine next end function canon_path","tags":"","loc":"proc/canon_path.html"},{"title":"dirname – Fortran-lang/fpm","text":"public function dirname(path) result(dir) Extract dirname from path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function dirname ( path ) result ( dir ) character ( * ), intent ( in ) :: path character (:), allocatable :: dir dir = path ( 1 : scan ( path , ' / \\' , back = . true .)) end function dirname","tags":"","loc":"proc/dirname.html"},{"title":"exists – Fortran-lang/fpm","text":"public function exists(filename) result(r) test if pathname already exists Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value logical","tags":"","loc":"proc/exists.html"},{"title":"get_dos_path – Fortran-lang/fpm","text":"public function get_dos_path(path, error) Ensure a windows path is converted to an 8.3 DOS path if it contains spaces\nNo need to convert if there are no spaces Read screen output Ensure there are no trailing slashes Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path type( error_t ), intent(out), allocatable :: error Return Value character(len=:), allocatable Source Code function get_dos_path ( path , error ) character ( len =* ), intent ( in ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: get_dos_path character (:), allocatable :: redirect , screen_output , line integer :: stat , cmdstat , iunit , last ! Non-Windows OS if ( get_os_type () /= OS_WINDOWS ) then get_dos_path = path return end if ! Trim path first get_dos_path = trim ( path ) !> No need to convert if there are no spaces has_spaces : if ( scan ( get_dos_path , ' ' ) > 0 ) then redirect = get_temp_filename () call execute_command_line ( 'cmd /c for %A in (\"' // path // '\") do @echo %~sA >' // redirect // ' 2>&1' ,& exitstat = stat , cmdstat = cmdstat ) !> Read screen output command_OK : if ( cmdstat == 0 . and . stat == 0 ) then allocate ( character ( len = 0 ) :: screen_output ) open ( newunit = iunit , file = redirect , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit screen_output = screen_output // line // ' ' end do ! Close and delete file close ( iunit , status = 'delete' ) else call fatal_error ( error , 'cannot read temporary file from successful DOS path evaluation' ) return endif else command_OK call fatal_error ( error , 'unsuccessful Windows->DOS path command' ) return end if command_OK get_dos_path = trim ( adjustl ( screen_output )) endif has_spaces !> Ensure there are no trailing slashes last = len_trim ( get_dos_path ) if ( last > 1 . and . get_dos_path ( last : last ) == '/' . or . get_dos_path ( last : last ) == '\\' ) get_dos_path = get_dos_path ( 1 : last - 1 ) end function get_dos_path","tags":"","loc":"proc/get_dos_path.html"},{"title":"get_local_prefix – Fortran-lang/fpm","text":"public function get_local_prefix(os) result(prefix) Determine the path prefix to the local folder. Used for installation, registry etc. Arguments Type Intent Optional Attributes Name integer, intent(in), optional :: os Platform identifier Return Value character(len=:), allocatable Installation prefix Source Code function get_local_prefix ( os ) result ( prefix ) !> Installation prefix character ( len = :), allocatable :: prefix !> Platform identifier integer , intent ( in ), optional :: os !> Default installation prefix on Unix platforms character ( len =* ), parameter :: default_prefix_unix = \"/usr/local\" !> Default installation prefix on Windows platforms character ( len =* ), parameter :: default_prefix_win = \"C:\\\" character(len=:), allocatable :: home if (os_is_unix(os)) then home=get_env('HOME','') if (home /= '' ) then prefix = join_path(home, \" . local \") else prefix = default_prefix_unix end if else home=get_env('APPDATA','') if (home /= '' ) then prefix = join_path(home, \" local \" ) else prefix = default_prefix_win end if end if end function get_local_prefix","tags":"","loc":"proc/get_local_prefix.html"},{"title":"get_temp_filename – Fortran-lang/fpm","text":"public function get_temp_filename() result(tempfile) Uses iso_c_binding Get a unused temporary filename\n Calls posix ‘tempnam’ - not recommended, but\n we have no security concerns for this application\n and use here is temporary.\nWorks with MinGW Arguments None Return Value character(len=:), allocatable Source Code function get_temp_filename () result ( tempfile ) ! use iso_c_binding , only : c_ptr , C_NULL_PTR , c_f_pointer integer , parameter :: MAX_FILENAME_LENGTH = 32768 character (:), allocatable :: tempfile type ( c_ptr ) :: c_tempfile_ptr character ( len = 1 ), pointer :: c_tempfile (:) interface function c_tempnam ( dir , pfx ) result ( tmp ) bind ( c , name = \"tempnam\" ) import type ( c_ptr ), intent ( in ), value :: dir type ( c_ptr ), intent ( in ), value :: pfx type ( c_ptr ) :: tmp end function c_tempnam subroutine c_free ( ptr ) BIND ( C , name = \"free\" ) import type ( c_ptr ), value :: ptr end subroutine c_free end interface c_tempfile_ptr = c_tempnam ( C_NULL_PTR , C_NULL_PTR ) call c_f_pointer ( c_tempfile_ptr , c_tempfile ,[ MAX_FILENAME_LENGTH ]) tempfile = f_string ( c_tempfile ) call c_free ( c_tempfile_ptr ) end function get_temp_filename","tags":"","loc":"proc/get_temp_filename.html"},{"title":"is_absolute_path – Fortran-lang/fpm","text":"public function is_absolute_path(path, is_unix) Returns .true. if provided path is absolute. ~ not treated as absolute. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path logical, intent(in), optional :: is_unix Return Value logical Source Code logical function is_absolute_path ( path , is_unix ) character ( len =* ), intent ( in ) :: path logical , optional , intent ( in ) :: is_unix character ( len =* ), parameter :: letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' logical :: is_unix_os if ( present ( is_unix )) then is_unix_os = is_unix else is_unix_os = os_is_unix () end if if ( is_unix_os ) then is_absolute_path = path ( 1 : 1 ) == '/' else if ( len ( path ) < 2 ) then is_absolute_path = . false . return end if is_absolute_path = index ( letters , path ( 1 : 1 )) /= 0 . and . path ( 2 : 2 ) == ':' end if end function is_absolute_path","tags":"","loc":"proc/is_absolute_path.html"},{"title":"is_dir – Fortran-lang/fpm","text":"public function is_dir(dir) test if a name matches an existing directory path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir Return Value logical Source Code logical function is_dir ( dir ) character ( * ), intent ( in ) :: dir integer :: stat select case ( get_os_type ()) case ( OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD ) call run ( \"test -d \" // dir , & & exitstat = stat , echo = . false ., verbose = . false .) case ( OS_WINDOWS ) call run ( 'cmd /c \"if not exist ' // windows_path ( dir ) // '\\ exit /B 1\"' , & & exitstat = stat , echo = . false ., verbose = . false .) end select is_dir = ( stat == 0 ) end function is_dir","tags":"","loc":"proc/is_dir.html"},{"title":"is_hidden_file – Fortran-lang/fpm","text":"public function is_hidden_file(file_basename) result(r) test if a file is hidden Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file_basename Return Value logical Source Code logical function is_hidden_file ( file_basename ) result ( r ) character ( * ), intent ( in ) :: file_basename if ( len ( file_basename ) <= 2 ) then r = . false . else r = str_begins_with_str ( file_basename , '.' ) end if end function is_hidden_file","tags":"","loc":"proc/is_hidden_file.html"},{"title":"join_path – Fortran-lang/fpm","text":"public function join_path(a1, a2, a3, a4, a5) result(path) Construct path by joining strings with os file separator Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: a1 character(len=*), intent(in) :: a2 character(len=*), intent(in), optional :: a3 character(len=*), intent(in), optional :: a4 character(len=*), intent(in), optional :: a5 Return Value character(len=:), allocatable Source Code function join_path ( a1 , a2 , a3 , a4 , a5 ) result ( path ) character ( len =* ), intent ( in ) :: a1 , a2 character ( len =* ), intent ( in ), optional :: a3 , a4 , a5 character ( len = :), allocatable :: path character ( len = 1 ) :: filesep logical , save :: has_cache = . false . character ( len = 1 ), save :: cache = '/' !$omp threadprivate(has_cache, cache) if ( has_cache ) then filesep = cache else select case ( get_os_type ()) case default filesep = '/' case ( OS_WINDOWS ) filesep = '\\' end select cache = filesep has_cache = . true . end if if ( a1 == \"\" ) then path = a2 else path = a1 // filesep // a2 end if if ( present ( a3 )) then path = path // filesep // a3 else return end if if ( present ( a4 )) then path = path // filesep // a4 else return end if if ( present ( a5 )) then path = path // filesep // a5 else return end if end function join_path","tags":"","loc":"proc/join_path.html"},{"title":"number_of_rows – Fortran-lang/fpm","text":"public function number_of_rows(s) result(nrows) Determine number or rows in a file given a LUN Arguments Type Intent Optional Attributes Name integer, intent(in) :: s Return Value integer Source Code integer function number_of_rows ( s ) result ( nrows ) integer , intent ( in ) :: s integer :: ios rewind ( s ) nrows = 0 do read ( s , * , iostat = ios ) if ( ios /= 0 ) exit nrows = nrows + 1 end do rewind ( s ) end function number_of_rows","tags":"","loc":"proc/number_of_rows.html"},{"title":"parent_dir – Fortran-lang/fpm","text":"public function parent_dir(path) result(dir) Extract dirname from path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function parent_dir ( path ) result ( dir ) character ( * ), intent ( in ) :: path character (:), allocatable :: dir dir = path ( 1 : scan ( path , ' / \\' , back = . true .) - 1 ) end function parent_dir","tags":"","loc":"proc/parent_dir.html"},{"title":"read_lines – Fortran-lang/fpm","text":"public function read_lines(filename) result(lines) read lines into an array of TYPE(STRING_T) variables Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value type( string_t ), allocatable, (:) Source Code function read_lines ( filename ) result ( lines ) character ( len =* ), intent ( in ) :: filename type ( string_t ), allocatable :: lines (:) integer :: i character ( len = :), allocatable :: content integer , allocatable :: first (:), last (:) content = read_text_file ( filename ) if ( len ( content ) == 0 ) then allocate ( lines ( 0 )) return end if call split_first_last ( content , eol , first , last ) ! TODO: \\r (< macOS X), \\n (>=macOS X/Linux/Unix), \\r\\n (Windows) ! allocate lines from file content string allocate ( lines ( size ( first ))) do i = 1 , size ( first ) allocate ( lines ( i )% s , source = content ( first ( i ): last ( i ))) end do end function read_lines","tags":"","loc":"proc/read_lines.html"},{"title":"read_lines_expanded – Fortran-lang/fpm","text":"public function read_lines_expanded(filename) result(lines) read lines into an array of TYPE(STRING_T) variables expanding tabs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value type( string_t ), allocatable, (:) Source Code function read_lines_expanded ( filename ) result ( lines ) character ( len =* ), intent ( in ) :: filename type ( string_t ), allocatable :: lines (:) integer :: i character ( len = :), allocatable :: content integer , allocatable :: first (:), last (:) content = read_text_file ( filename ) if ( len ( content ) == 0 ) then allocate ( lines ( 0 )) return end if call split_first_last ( content , eol , first , last ) ! TODO: \\r (< macOS X), \\n (>=macOS X/Linux/Unix), \\r\\n (Windows) ! allocate lines from file content string allocate ( lines ( size ( first ))) do i = 1 , size ( first ) allocate ( lines ( i )% s , source = dilate ( content ( first ( i ): last ( i )))) end do end function read_lines_expanded","tags":"","loc":"proc/read_lines_expanded.html"},{"title":"unix_path – Fortran-lang/fpm","text":"public function unix_path(path) result(nixpath) Replace file system separators for unix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function unix_path ( path ) result ( nixpath ) character ( * ), intent ( in ) :: path character (:), allocatable :: nixpath integer :: idx nixpath = path idx = index ( nixpath , '\\') do while(idx > 0) nixpath(idx:idx) = ' / ' idx = index(nixpath,' \\' ) end do end function unix_path","tags":"","loc":"proc/unix_path.html"},{"title":"which – Fortran-lang/fpm","text":"public function which(command) result(pathname) Name which ( 3 f ) - [ M_io : ENVIRONMENT ] given a command name find the pathname by searching the directories in the environment variable $ PATH ( LICENSE : PD ) Syntax function which(command) result(pathname) character(len=*),intent(in) :: command\ncharacter(len=:),allocatable :: pathname Description Given a command name find the first file with that name in the directories specified by the environment variable $ PATH . options COMMAND the command to search for Returns PATHNAME the first pathname found in the current user path . Returns blank if the command is not found . Example Sample program: Checking the error message and counting lines: program demo_which use M_io , only : which implicit none write ( * , * ) ' ls is ' , which ( ' ls ' ) write ( * , * ) ' dir is ' , which ( ' dir ' ) write ( * , * ) ' install is ' , which ( ' install ' ) end program demo_which Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: command Return Value character(len=:), allocatable Source Code function which ( command ) result ( pathname ) character ( len =* ), intent ( in ) :: command character ( len = :), allocatable :: pathname , checkon , paths (:), exts (:) integer :: i , j pathname = '' call split ( get_env ( 'PATH' ), paths , delimiters = merge ( ';' , ':' , separator () == '\\')) SEARCH: do i=1,size(paths) checkon=trim(join_path(trim(paths(i)),command)) select case(separator()) case(' / ') if(exists(checkon))then pathname=checkon exit SEARCH endif case(' \\ ') if(exists(checkon))then pathname=checkon exit SEARCH endif if(exists(checkon//' . bat '))then pathname=checkon//' . bat ' exit SEARCH endif if(exists(checkon//' . exe '))then pathname=checkon//' . exe ' exit SEARCH endif call split(get_env(' PATHEXT '),exts,delimiters=' ; ') do j=1,size(exts) if(exists(checkon//' . '//trim(exts(j))))then pathname=checkon//' . ' // trim ( exts ( j )) exit SEARCH endif enddo end select enddo SEARCH end function which","tags":"","loc":"proc/which.html"},{"title":"windows_path – Fortran-lang/fpm","text":"public function windows_path(path) result(winpath) Replace file system separators for windows Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function windows_path ( path ) result ( winpath ) character ( * ), intent ( in ) :: path character (:), allocatable :: winpath integer :: idx winpath = path idx = index ( winpath , '/' ) do while ( idx > 0 ) winpath ( idx : idx ) = '\\' idx = index(winpath,' / ' ) end do end function windows_path","tags":"","loc":"proc/windows_path.html"},{"title":"delete_file – Fortran-lang/fpm","text":"public subroutine delete_file(file) delete a file by filename Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file Source Code subroutine delete_file ( file ) character ( len =* ), intent ( in ) :: file logical :: exist integer :: unit inquire ( file = file , exist = exist ) if ( exist ) then open ( file = file , newunit = unit ) close ( unit , status = \"delete\" ) end if end subroutine delete_file","tags":"","loc":"proc/delete_file.html"},{"title":"execute_and_read_output – Fortran-lang/fpm","text":"public subroutine execute_and_read_output(cmd, output, error, verbose) Execute command line and return output as a string. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: cmd Command to execute. character(len=:), intent(out), allocatable :: output Command line output. type( error_t ), intent(out), allocatable :: error Error to handle. logical, intent(in), optional :: verbose Print additional information if true.","tags":"","loc":"proc/execute_and_read_output.html"},{"title":"fileclose – Fortran-lang/fpm","text":"public subroutine fileclose(lun, ier) simple close of a LUN. On error show message and stop (by default) Arguments Type Intent Optional Attributes Name integer, intent(in) :: lun integer, intent(out), optional :: ier Source Code subroutine fileclose ( lun , ier ) integer , intent ( in ) :: lun integer , intent ( out ), optional :: ier character ( len = 256 ) :: message integer :: ios if ( lun /=- 1 ) then close ( unit = lun , iostat = ios , iomsg = message ) if ( ios /= 0 ) then if ( present ( ier )) then ier = ios else call fpm_stop ( 4 , '*fileclose*:' // trim ( message )) endif endif endif end subroutine fileclose","tags":"","loc":"proc/fileclose.html"},{"title":"fileopen – Fortran-lang/fpm","text":"public subroutine fileopen(filename, lun, ier) procedure to open filename as a sequential “text” file Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename integer, intent(out) :: lun integer, intent(out), optional :: ier Source Code subroutine fileopen ( filename , lun , ier ) character ( len =* ), intent ( in ) :: filename integer , intent ( out ) :: lun integer , intent ( out ), optional :: ier integer :: ios character ( len = 256 ) :: message message = ' ' ios = 0 if ( filename /= ' ' ) then open ( file = filename , & & newunit = lun , & & form = 'formatted' , & ! FORM = FORMATTED | UNFORMATTED & access = 'sequential' , & ! ACCESS = SEQUENTIAL| DIRECT | STREAM & action = 'write' , & ! ACTION = READ|WRITE| READWRITE & position = 'rewind' , & ! POSITION= ASIS | REWIND | APPEND & status = 'new' , & ! STATUS = NEW| REPLACE| OLD| SCRATCH| UNKNOWN & iostat = ios , & & iomsg = message ) else lun = stdout ios = 0 endif if ( ios /= 0 ) then lun =- 1 if ( present ( ier )) then ier = ios else call fpm_stop ( 3 , '*fileopen*:' // filename // ':' // trim ( message )) endif endif end subroutine fileopen","tags":"","loc":"proc/fileopen.html"},{"title":"filewrite – Fortran-lang/fpm","text":"public subroutine filewrite(filename, filedata) procedure to write filedata to file filename Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename character(len=*), intent(in) :: filedata (:) Source Code subroutine filewrite ( filename , filedata ) character ( len =* ), intent ( in ) :: filename character ( len =* ), intent ( in ) :: filedata (:) integer :: lun , i , ios character ( len = 256 ) :: message call fileopen ( filename , lun ) if ( lun /=- 1 ) then ! program currently stops on error on open, but might ! want it to continue so -1 (unallowed LUN) indicates error ! write file do i = 1 , size ( filedata ) write ( lun , '(a)' , iostat = ios , iomsg = message ) trim ( filedata ( i )) if ( ios /= 0 ) then call fpm_stop ( 5 , '*filewrite*:' // filename // ':' // trim ( message )) endif enddo endif ! close file call fileclose ( lun ) end subroutine filewrite","tags":"","loc":"proc/filewrite.html"},{"title":"get_home – Fortran-lang/fpm","text":"public subroutine get_home(home, error) Get the HOME directory on Unix and the %USERPROFILE% directory on Windows. Arguments Type Intent Optional Attributes Name character(len=:), intent(out), allocatable :: home type( error_t ), intent(out), allocatable :: error Source Code subroutine get_home ( home , error ) character ( len = :), allocatable , intent ( out ) :: home type ( error_t ), allocatable , intent ( out ) :: error if ( os_is_unix ()) then home = get_env ( 'HOME' , '' ) if ( home == '' ) then call fatal_error ( error , \"Couldn't retrieve 'HOME' variable\" ) return end if else home = get_env ( 'USERPROFILE' , '' ) if ( home == '' ) then call fatal_error ( error , \"Couldn't retrieve '%USERPROFILE%' variable\" ) return end if end if end subroutine get_home","tags":"","loc":"proc/get_home.html"},{"title":"getline – Fortran-lang/fpm","text":"public subroutine getline(unit, line, iostat, iomsg) NAME getline(3f) - [M_io:READ] read a line of arbintrary length from specified\n LUN into allocatable string (up to system line length limit)\n(LICENSE:PD) SYNTAX subroutine getline(unit,line,iostat,iomsg) integer,intent(in) :: unit\ncharacter(len=:),allocatable,intent(out) :: line\ninteger,intent(out) :: iostat\ncharacter(len=:), allocatable, optional :: iomsg DESCRIPTION Read a line of any length up to programming environment maximum line length . Requires Fortran 2003 +. It is primarily expected to be used when reading input which will then be parsed or echoed . The input file must have a PAD attribute of YES for the function to work properly , which is typically true . The simple use of a loop that repeatedly re - allocates a character variable in addition to reading the input file one buffer at a time could ( depending on the programming environment used ) be inefficient , as it could reallocate and allocate memory used for the output string with each buffer read . OPTIONS LINE The line read when IOSTAT returns as zero . LUN LUN ( Fortran logical I / O unit ) number of file open and ready to read . IOSTAT status returned by READ ( IOSTAT = IOS ) . If not zero , an error occurred or an end - of - file or end - of - record was encountered . IOMSG error message returned by system when IOSTAT is not zero . EXAMPLE Sample program: program demo_getline use , intrinsic :: iso_fortran_env , only : stdin => input_unit use , intrinsic :: iso_fortran_env , only : iostat_end use FPM_filesystem , only : getline implicit none integer :: iostat character ( len =:), allocatable :: line , iomsg open ( unit = stdin , pad = ' yes ' ) INFINITE : do call getline ( stdin , line , iostat , iomsg ) if ( iostat /= 0 ) exit INFINITE write ( * , ' ( a ) ')' [ ' //line//']' enddo INFINITE if ( iostat /= iostat_end ) then write ( * , * ) ' error reading input : ' , iomsg endif end program demo_getline Arguments Type Intent Optional Attributes Name integer, intent(in) :: unit Formatted IO unit character(len=:), intent(out), allocatable :: line Line to read integer, intent(out) :: iostat Status of operation character(len=:), optional, allocatable :: iomsg Error message Source Code subroutine getline ( unit , line , iostat , iomsg ) !> Formatted IO unit integer , intent ( in ) :: unit !> Line to read character ( len = :), allocatable , intent ( out ) :: line !> Status of operation integer , intent ( out ) :: iostat !> Error message character ( len = :), allocatable , optional :: iomsg integer , parameter :: BUFFER_SIZE = 1024 character ( len = BUFFER_SIZE ) :: buffer character ( len = 256 ) :: msg integer :: size integer :: stat allocate ( character ( len = 0 ) :: line ) do read ( unit , '(a)' , advance = 'no' , iostat = stat , iomsg = msg , size = size ) & & buffer if ( stat > 0 ) exit line = line // buffer (: size ) if ( stat < 0 ) then if ( is_iostat_eor ( stat )) then stat = 0 end if exit end if end do if ( stat /= 0 ) then if ( present ( iomsg )) iomsg = trim ( msg ) end if iostat = stat end subroutine getline","tags":"","loc":"proc/getline.html"},{"title":"list_files – Fortran-lang/fpm","text":"public recursive subroutine list_files(dir, files, recurse) Get file & directory names in directory dir using iso_c_binding. File/directory names return are relative to cwd, ie. preprended with dir Includes files starting with . except current directory and parent directory Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir type( string_t ), intent(out), allocatable :: files (:) logical, intent(in), optional :: recurse Source Code recursive subroutine list_files ( dir , files , recurse ) character ( len =* ), intent ( in ) :: dir type ( string_t ), allocatable , intent ( out ) :: files (:) logical , intent ( in ), optional :: recurse integer :: i type ( string_t ), allocatable :: dir_files (:) type ( string_t ), allocatable :: sub_dir_files (:) type ( c_ptr ) :: dir_handle type ( c_ptr ) :: dir_entry_c character ( len = :, kind = c_char ), allocatable :: fortran_name character ( len = :), allocatable :: string_fortran integer , parameter :: N_MAX = 256 type ( string_t ) :: files_tmp ( N_MAX ) integer ( kind = c_int ) :: r if ( c_is_dir ( dir ( 1 : len_trim ( dir )) // c_null_char ) == 0 ) then allocate ( files ( 0 )) return end if dir_handle = c_opendir ( dir ( 1 : len_trim ( dir )) // c_null_char ) if (. not . c_associated ( dir_handle )) then print * , 'c_opendir() failed' error stop end if i = 0 allocate ( files ( 0 )) do dir_entry_c = c_readdir ( dir_handle ) if (. not . c_associated ( dir_entry_c )) then exit else string_fortran = f_string ( c_get_d_name ( dir_entry_c )) if (( string_fortran == '.' . or . string_fortran == '..' )) then cycle end if i = i + 1 if ( i > N_MAX ) then files = [ files , files_tmp ] i = 1 end if files_tmp ( i )% s = join_path ( dir , string_fortran ) end if end do r = c_closedir ( dir_handle ) if ( r /= 0 ) then print * , 'c_closedir() failed' error stop end if if ( i > 0 ) then files = [ files , files_tmp ( 1 : i )] end if if ( present ( recurse )) then if ( recurse ) then allocate ( sub_dir_files ( 0 )) do i = 1 , size ( files ) if ( c_is_dir ( files ( i )% s // c_null_char ) /= 0 ) then call list_files ( files ( i )% s , dir_files , recurse = . true .) sub_dir_files = [ sub_dir_files , dir_files ] end if end do files = [ files , sub_dir_files ] end if end if end subroutine list_files","tags":"","loc":"proc/list_files.html"},{"title":"mkdir – Fortran-lang/fpm","text":"public subroutine mkdir(dir, echo) Create a directory. Create subdirectories as needed Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir logical, intent(in), optional :: echo Source Code subroutine mkdir ( dir , echo ) character ( len =* ), intent ( in ) :: dir logical , intent ( in ), optional :: echo integer :: stat if ( is_dir ( dir )) return select case ( get_os_type ()) case ( OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD ) call run ( 'mkdir -p ' // dir , exitstat = stat , echo = echo , verbose = . false .) case ( OS_WINDOWS ) call run ( \"mkdir \" // windows_path ( dir ), & & echo = echo , exitstat = stat , verbose = . false .) end select if ( stat /= 0 ) then call fpm_stop ( 1 , '*mkdir*:directory creation failed' ) end if end subroutine mkdir","tags":"","loc":"proc/mkdir.html"},{"title":"os_delete_dir – Fortran-lang/fpm","text":"public subroutine os_delete_dir(is_unix, dir, echo) Delete directory using system OS remove directory commands Arguments Type Intent Optional Attributes Name logical, intent(in) :: is_unix character(len=*), intent(in) :: dir logical, intent(in), optional :: echo Source Code subroutine os_delete_dir ( is_unix , dir , echo ) logical , intent ( in ) :: is_unix character ( len =* ), intent ( in ) :: dir logical , intent ( in ), optional :: echo if ( is_unix ) then call run ( 'rm -rf ' // dir , echo = echo , verbose = . false .) else call run ( 'rmdir /s/q ' // dir , echo = echo , verbose = . false .) end if end subroutine os_delete_dir","tags":"","loc":"proc/os_delete_dir.html"},{"title":"run – Fortran-lang/fpm","text":"public subroutine run(cmd, echo, exitstat, verbose, redirect) Name run(3f) - execute specified system command and selectively echo\ncommand and output to a file and/or stdout.\n(LICENSE:MIT) Syntax subroutine run(cmd,echo,exitstat,verbose,redirect)\n\n character(len=*), intent(in) :: cmd\n logical,intent(in),optional :: echo\n integer, intent(out),optional :: exitstat\n logical, intent(in), optional :: verbose\n character(*), intent(in), optional :: redirect Description Execute the specified system command. Optionally echo the command before execution return the system exit status of the command. redirect the output of the command to a file. echo command output to stdout Calling run(3f) is preferred to direct calls to\n execute_command_line(3f) in the fpm(1) source to provide a standard\n interface where output modes can be specified. Options CMD System command to execute ECHO Whether to echo the command being executed or not Defaults to . TRUE . . VERBOSE Whether to redirect the command output to a null device or not Defaults to . TRUE . . REDIRECT Filename to redirect stdout and stderr of the command into . If generated it is closed before run ( 3 f ) returns . EXITSTAT The system exit status of the command when supported by the system . If not present and a non - zero status is generated program termination occurs . Example Sample program: Checking the error message and counting lines: program demo_run use fpm_filesystem , only : run implicit none logical , parameter :: T =. true ., F =. false . integer :: exitstat character ( len =:), allocatable :: cmd cmd = ' ls - ltrasd * . md ' call run ( cmd ) call run ( cmd , exitstat = exitstat ) call run ( cmd , echo = F ) call run ( cmd , verbose = F ) end program demo_run Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: cmd logical, intent(in), optional :: echo integer, intent(out), optional :: exitstat logical, intent(in), optional :: verbose character(len=*), intent(in), optional :: redirect Source Code subroutine run ( cmd , echo , exitstat , verbose , redirect ) character ( len =* ), intent ( in ) :: cmd logical , intent ( in ), optional :: echo integer , intent ( out ), optional :: exitstat logical , intent ( in ), optional :: verbose character ( * ), intent ( in ), optional :: redirect integer :: cmdstat character ( len = 256 ) :: cmdmsg , iomsg logical :: echo_local , verbose_local character (:), allocatable :: redirect_str character (:), allocatable :: line integer :: stat , fh , iostat if ( present ( echo )) then echo_local = echo else echo_local = . true . end if if ( present ( verbose )) then verbose_local = verbose else verbose_local = . true . end if if ( present ( redirect )) then if ( redirect /= '' ) then redirect_str = \">\" // redirect // \" 2>&1\" else redirect_str = \"\" endif else if ( verbose_local ) then ! No redirection but verbose output redirect_str = \"\" else ! No redirection and non-verbose output if ( os_is_unix ()) then redirect_str = \" >/dev/null 2>&1\" else redirect_str = \" >NUL 2>&1\" end if end if end if if ( echo_local ) print * , '+ ' , cmd !//redirect_str call execute_command_line ( cmd // redirect_str , exitstat = stat , cmdstat = cmdstat , cmdmsg = cmdmsg ) if ( cmdstat /= 0 ) then write ( * , '(a)' ) ':failed command ' // cmd // redirect_str call fpm_stop ( 1 , '*run*:' // trim ( cmdmsg )) endif if ( verbose_local . and . present ( redirect )) then open ( newunit = fh , file = redirect , status = 'old' , iostat = iostat , iomsg = iomsg ) if ( iostat == 0 ) then do call getline ( fh , line , iostat ) if ( iostat /= 0 ) exit write ( * , '(A)' ) trim ( line ) end do else write ( * , '(A)' ) trim ( iomsg ) endif close ( fh ) end if if ( present ( exitstat )) then exitstat = stat elseif ( stat /= 0 ) then call fpm_stop ( stat , '*run*: Command ' // cmd // redirect_str // ' returned a non-zero status code' ) end if end subroutine run","tags":"","loc":"proc/run~2.html"},{"title":"warnwrite – Fortran-lang/fpm","text":"public subroutine warnwrite(fname, data) write trimmed character data to a file if it does not exist Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: fname character(len=*), intent(in) :: data (:) Source Code subroutine warnwrite ( fname , data ) character ( len =* ), intent ( in ) :: fname character ( len =* ), intent ( in ) :: data (:) if (. not . exists ( fname )) then call filewrite ( fname , data ) else write ( stderr , '(*(g0,1x))' ) ' ' , fname ,& & 'already exists. Not overwriting' endif end subroutine warnwrite","tags":"","loc":"proc/warnwrite.html"},{"title":"change_directory – Fortran-lang/fpm","text":"public subroutine change_directory(path, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path type( error_t ), intent(out), allocatable :: error Source Code subroutine change_directory ( path , error ) character ( len =* ), intent ( in ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: cpath (:) integer :: stat allocate ( cpath ( len ( path ) + 1 )) call f_c_character ( path , cpath , len ( path ) + 1 ) stat = chdir_ ( cpath ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to change directory to '\" // path // \"'\" ) end if end subroutine change_directory","tags":"","loc":"proc/change_directory.html"},{"title":"convert_to_absolute_path – Fortran-lang/fpm","text":"public subroutine convert_to_absolute_path(path, error) Converts a path to an absolute, canonical path. Arguments Type Intent Optional Attributes Name character(len=:), intent(inout), allocatable :: path type( error_t ), intent(out), allocatable :: error","tags":"","loc":"proc/convert_to_absolute_path.html"},{"title":"get_absolute_path – Fortran-lang/fpm","text":"public subroutine get_absolute_path(path, absolute_path, error) Determine the canonical, absolute path for the given path.\nExpands home folder (~) on both Unix and Windows. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path character(len=:), intent(out), allocatable :: absolute_path type( error_t ), intent(out), allocatable :: error","tags":"","loc":"proc/get_absolute_path.html"},{"title":"get_absolute_path_by_cd – Fortran-lang/fpm","text":"public subroutine get_absolute_path_by_cd(path, absolute_path, error) Alternative to get_absolute_path that uses chdir / _chdir to determine the absolute path. get_absolute_path is preferred but get_absolute_path_by_cd can be used in bootstrap mode. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path character(len=:), intent(out), allocatable :: absolute_path type( error_t ), intent(out), allocatable :: error","tags":"","loc":"proc/get_absolute_path_by_cd.html"},{"title":"get_current_directory – Fortran-lang/fpm","text":"public subroutine get_current_directory(path, error) Arguments Type Intent Optional Attributes Name character(len=:), intent(out), allocatable :: path type( error_t ), intent(out), allocatable :: error Source Code subroutine get_current_directory ( path , error ) character ( len = :), allocatable , intent ( out ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: cpath (:) type ( c_ptr ) :: tmp allocate ( cpath ( buffersize )) tmp = getcwd_ ( cpath , buffersize ) if ( c_associated ( tmp )) then call c_f_character ( cpath , path ) else call fatal_error ( error , \"Failed to retrieve current directory\" ) end if end subroutine get_current_directory","tags":"","loc":"proc/get_current_directory.html"},{"title":"check_and_read_pkg_data – Fortran-lang/fpm","text":"public subroutine check_and_read_pkg_data(json, node, download_url, version, error) Arguments Type Intent Optional Attributes Name type(json_object), intent(inout) :: json class( dependency_node_t ), intent(in) :: node character(len=:), intent(out), allocatable :: download_url type( version_t ), intent(out) :: version type( error_t ), intent(out), allocatable :: error","tags":"","loc":"proc/check_and_read_pkg_data.html"},{"title":"destroy_dependency_node – Fortran-lang/fpm","text":"public elemental subroutine destroy_dependency_node(self) Destructor Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self Source Code elemental subroutine destroy_dependency_node ( self ) class ( dependency_node_t ), intent ( inout ) :: self integer :: ierr call dependency_destroy ( self ) deallocate ( self % version , stat = ierr ) deallocate ( self % proj_dir , stat = ierr ) deallocate ( self % revision , stat = ierr ) self % done = . false . self % update = . false . self % cached = . false . end subroutine destroy_dependency_node","tags":"","loc":"proc/destroy_dependency_node.html"},{"title":"new_dependency_node – Fortran-lang/fpm","text":"public subroutine new_dependency_node(self, dependency, version, proj_dir, update) Create a new dependency node from a configuration Arguments Type Intent Optional Attributes Name type( dependency_node_t ), intent(out) :: self Instance of the dependency node type( dependency_config_t ), intent(in) :: dependency Dependency configuration data type( version_t ), intent(in), optional :: version Version of the dependency character(len=*), intent(in), optional :: proj_dir Installation prefix of the dependency logical, intent(in), optional :: update Dependency should be updated Source Code subroutine new_dependency_node ( self , dependency , version , proj_dir , update ) !> Instance of the dependency node type ( dependency_node_t ), intent ( out ) :: self !> Dependency configuration data type ( dependency_config_t ), intent ( in ) :: dependency !> Version of the dependency type ( version_t ), intent ( in ), optional :: version !> Installation prefix of the dependency character ( len =* ), intent ( in ), optional :: proj_dir !> Dependency should be updated logical , intent ( in ), optional :: update self % dependency_config_t = dependency if ( present ( version )) then self % version = version end if if ( present ( proj_dir )) then self % proj_dir = proj_dir end if if ( present ( update )) then self % update = update end if end subroutine new_dependency_node","tags":"","loc":"proc/new_dependency_node.html"},{"title":"new_dependency_tree – Fortran-lang/fpm","text":"public subroutine new_dependency_tree(self, verbosity, cache) Create a new dependency tree Arguments Type Intent Optional Attributes Name type( dependency_tree_t ), intent(out) :: self Instance of the dependency tree integer, intent(in), optional :: verbosity Verbosity of printout character(len=*), intent(in), optional :: cache Name of the cache file Source Code subroutine new_dependency_tree ( self , verbosity , cache ) !> Instance of the dependency tree type ( dependency_tree_t ), intent ( out ) :: self !> Verbosity of printout integer , intent ( in ), optional :: verbosity !> Name of the cache file character ( len =* ), intent ( in ), optional :: cache call resize ( self % dep ) self % dep_dir = join_path ( \"build\" , \"dependencies\" ) if ( present ( verbosity )) self % verbosity = verbosity if ( present ( cache )) self % cache = cache end subroutine new_dependency_tree","tags":"","loc":"proc/new_dependency_tree.html"},{"title":"resize – Fortran-lang/fpm","text":"public interface resize Overloaded reallocation interface Module Procedures private pure subroutine resize_dependency_node(var, n) Reallocate a list of dependencies Arguments Type Intent Optional Attributes Name type( dependency_node_t ), intent(inout), allocatable :: var (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size","tags":"","loc":"interface/resize~3.html"},{"title":"fpm_version – Fortran-lang/fpm","text":"public function fpm_version() Return the current fpm version from fpm_version_ID as a version type Arguments None Return Value type( version_t ) Source Code type ( version_t ) function fpm_version () type ( error_t ), allocatable :: error ! Fallback to last known version in case of undefined macro #ifndef FPM_RELEASE_VERSION # define FPM_RELEASE_VERSION 0.10.1 #endif ! Accept solution from https://stackoverflow.com/questions/31649691/stringify-macro-with-gnu-gfortran ! which provides the \"easiest\" way to pass a macro to a string in Fortran complying with both ! gfortran's \"traditional\" cpp and the standard cpp syntaxes #ifdef __GFORTRAN__ /* traditional-cpp stringification */ # define STRINGIFY_START(X) \"& # define STRINGIFY_END(X) &X\" #else /* default stringification */ # define STRINGIFY_(X) #X # define STRINGIFY_START(X) & # define STRINGIFY_END(X) STRINGIFY_(X) #endif character ( len = :), allocatable :: ver_string ver_string = STRINGIFY_START ( FPM_RELEASE_VERSION ) STRINGIFY_END ( FPM_RELEASE_VERSION ) call new_version ( fpm_version , ver_string , error ) if ( allocated ( error )) call fpm_stop ( 1 , '*fpm*:internal error: cannot get version - ' // error % message ) end function fpm_version","tags":"","loc":"proc/fpm_version.html"},{"title":"new_preprocess_config – Fortran-lang/fpm","text":"public subroutine new_preprocess_config(self, table, error) Construct a new preprocess configuration from TOML data structure Arguments Type Intent Optional Attributes Name type( preprocess_config_t ), intent(out) :: self Instance of the preprocess configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure. type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_preprocess_config ( self , table , error ) !> Instance of the preprocess configuration type ( preprocess_config_t ), intent ( out ) :: self !> Instance of the TOML data structure. type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call table % get_key ( self % name ) call get_list ( table , \"suffixes\" , self % suffixes , error ) if ( allocated ( error )) return call get_list ( table , \"directories\" , self % directories , error ) if ( allocated ( error )) return call get_list ( table , \"macros\" , self % macros , error ) if ( allocated ( error )) return end subroutine new_preprocess_config","tags":"","loc":"proc/new_preprocess_config.html"},{"title":"new_preprocessors – Fortran-lang/fpm","text":"public subroutine new_preprocessors(preprocessors, table, error) Construct new preprocess array from a TOML data structure. Arguments Type Intent Optional Attributes Name type( preprocess_config_t ), intent(out), allocatable :: preprocessors (:) Instance of the preprocess configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_preprocessors ( preprocessors , table , error ) !> Instance of the preprocess configuration type ( preprocess_config_t ), allocatable , intent ( out ) :: preprocessors (:) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: node type ( toml_key ), allocatable :: list (:) integer :: iprep , stat call table % get_keys ( list ) ! An empty table is not allowed if ( size ( list ) == 0 ) then call syntax_error ( error , \"No preprocessors defined\" ) end if allocate ( preprocessors ( size ( list ))) do iprep = 1 , size ( list ) call get_value ( table , list ( iprep )% key , node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Preprocessor \" // list ( iprep )% key // \" must be a table entry\" ) exit end if call new_preprocess_config ( preprocessors ( iprep ), node , error ) if ( allocated ( error )) exit end do end subroutine new_preprocessors","tags":"","loc":"proc/new_preprocessors.html"},{"title":"cmd_publish – Fortran-lang/fpm","text":"public subroutine cmd_publish(settings) The publish command first builds the root package to obtain all the relevant information such as the\npackage version. It then creates a tarball of the package and uploads it to the registry.\nChecks before uploading the package. Arguments Type Intent Optional Attributes Name type( fpm_publish_settings ), intent(inout) :: settings","tags":"","loc":"proc/cmd_publish.html"},{"title":"get_global_settings – Fortran-lang/fpm","text":"public subroutine get_global_settings(global_settings, error) Obtain global settings from the global config file. Arguments Type Intent Optional Attributes Name type( fpm_global_settings ), intent(inout) :: global_settings Global settings to be obtained. type( error_t ), intent(out), allocatable :: error Error reading config file.","tags":"","loc":"proc/get_global_settings.html"},{"title":"get_registry_settings – Fortran-lang/fpm","text":"public subroutine get_registry_settings(table, global_settings, error) Read registry settings from the global config file. Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout), target :: table The [registry] subtable from the global config file. type( fpm_global_settings ), intent(inout) :: global_settings The global settings which can be filled with the registry settings. type( error_t ), intent(out), allocatable :: error Error handling.","tags":"","loc":"proc/get_registry_settings.html"},{"title":"FPM_SCOPE_NAME – Fortran-lang/fpm","text":"public function FPM_SCOPE_NAME(flag) result(name) Return the character name of a scope flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: flag Return Value character(len=:), allocatable Source Code function FPM_SCOPE_NAME ( flag ) result ( name ) integer , intent ( in ) :: flag character ( len = :), allocatable :: name select case ( flag ) case ( FPM_SCOPE_UNKNOWN ); name = \"FPM_SCOPE_UNKNOWN\" case ( FPM_SCOPE_LIB ); name = \"FPM_SCOPE_LIB\" case ( FPM_SCOPE_DEP ); name = \"FPM_SCOPE_DEP\" case ( FPM_SCOPE_APP ); name = \"FPM_SCOPE_APP\" case ( FPM_SCOPE_TEST ); name = \"FPM_SCOPE_TEST\" case ( FPM_SCOPE_EXAMPLE ); name = \"FPM_SCOPE_EXAMPLE\" case default ; name = \"INVALID\" end select end function FPM_SCOPE_NAME","tags":"","loc":"proc/fpm_scope_name.html"},{"title":"show_model – Fortran-lang/fpm","text":"public subroutine show_model(model) Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(in) :: model Source Code subroutine show_model ( model ) ! Prints a human readable representation of the Model type ( fpm_model_t ), intent ( in ) :: model print * , info_model ( model ) end subroutine show_model","tags":"","loc":"proc/show_model.html"},{"title":"get_exe_name_with_suffix – Fortran-lang/fpm","text":"public function get_exe_name_with_suffix(source) result(suffixed) Build an executable name with suffix. Safe routine that always returns an allocated string Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(in) :: source Return Value character(len=:), allocatable Source Code function get_exe_name_with_suffix ( source ) result ( suffixed ) type ( srcfile_t ), intent ( in ) :: source character ( len = :), allocatable :: suffixed if ( allocated ( source % exe_name )) then if ( get_os_type () == OS_WINDOWS ) then suffixed = source % exe_name // '.exe' else suffixed = source % exe_name end if else suffixed = \"\" endif end function get_exe_name_with_suffix","tags":"","loc":"proc/get_exe_name_with_suffix.html"},{"title":"add_executable_sources – Fortran-lang/fpm","text":"public subroutine add_executable_sources(sources, executables, scope, auto_discover, with_f_ext, error) Add to sources using the executable and test entries in the manifest and\napplies any executable-specific overrides such as executable%name .\nAdds all sources (including modules) from each executable%source_dir Compare lowercase strings to allow auto-discovery of pre-processed extensions Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(inout), allocatable, target :: sources (:) List of [[srcfile_t]] objects to append to. Allocated if not allocated class( executable_config_t ), intent(in) :: executables (:) List of [[executable_config_t]] entries from manifest integer, intent(in) :: scope Scope to apply to the discovered sources: either FPM_SCOPE_APP or FPM_SCOPE_TEST , see fpm_model logical, intent(in) :: auto_discover If .false. only executables and tests specified in the manifest are added to sources type( string_t ), intent(in), optional :: with_f_ext (:) Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine add_executable_sources ( sources , executables , scope , auto_discover , with_f_ext , error ) !> List of `[[srcfile_t]]` objects to append to. Allocated if not allocated type ( srcfile_t ), allocatable , intent ( inout ), target :: sources (:) !> List of `[[executable_config_t]]` entries from manifest class ( executable_config_t ), intent ( in ) :: executables (:) !> Scope to apply to the discovered sources: either `FPM_SCOPE_APP` or `FPM_SCOPE_TEST`, see [[fpm_model]] integer , intent ( in ) :: scope !> If `.false.` only executables and tests specified in the manifest are added to `sources` logical , intent ( in ) :: auto_discover !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j type ( string_t ), allocatable :: exe_dirs (:) type ( srcfile_t ) :: exe_source call get_executable_source_dirs ( exe_dirs , executables ) do i = 1 , size ( exe_dirs ) call add_sources_from_dir ( sources , exe_dirs ( i )% s , scope , & with_executables = auto_discover , with_f_ext = with_f_ext , recurse = . false ., error = error ) if ( allocated ( error )) then return end if end do exe_loop : do i = 1 , size ( executables ) ! Check if executable already discovered automatically ! and apply any overrides do j = 1 , size ( sources ) !> Compare lowercase strings to allow auto-discovery of pre-processed extensions if ( lower ( basename ( sources ( j )% file_name , suffix = . true .)) == lower ( executables ( i )% main ) . and .& canon_path ( dirname ( sources ( j )% file_name )) == & canon_path ( executables ( i )% source_dir ) ) then sources ( j )% exe_name = executables ( i )% name if ( allocated ( executables ( i )% link )) then sources ( j )% link_libraries = executables ( i )% link end if sources ( j )% unit_type = FPM_UNIT_PROGRAM cycle exe_loop end if end do ! Add if not already discovered (auto_discovery off) associate ( exe => executables ( i )) exe_source = parse_source ( join_path ( exe % source_dir , exe % main ), with_f_ext , error ) exe_source % exe_name = exe % name if ( allocated ( exe % link )) then exe_source % link_libraries = exe % link end if exe_source % unit_type = FPM_UNIT_PROGRAM exe_source % unit_scope = scope end associate if ( allocated ( error )) return if (. not . allocated ( sources )) then sources = [ exe_source ] else sources = [ sources , exe_source ] end if end do exe_loop end subroutine add_executable_sources","tags":"","loc":"proc/add_executable_sources.html"},{"title":"add_sources_from_dir – Fortran-lang/fpm","text":"public subroutine add_sources_from_dir(sources, directory, scope, with_executables, with_f_ext, recurse, error) Add to sources by looking for source files in directory Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(inout), allocatable, target :: sources (:) List of [[srcfile_t]] objects to append to. Allocated if not allocated character(len=*), intent(in) :: directory Directory in which to search for source files integer, intent(in) :: scope Scope to apply to the discovered sources, see fpm_model for enumeration logical, intent(in), optional :: with_executables Executable sources (fortran program s) are ignored unless with_executables=.true. type( string_t ), intent(in), optional :: with_f_ext (:) Additional user-defined (preprocessor) extensions that should be treated as Fortran sources logical, intent(in), optional :: recurse Whether to recursively search subdirectories, default is .true. type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine add_sources_from_dir ( sources , directory , scope , with_executables , with_f_ext , recurse , error ) !> List of `[[srcfile_t]]` objects to append to. Allocated if not allocated type ( srcfile_t ), allocatable , intent ( inout ), target :: sources (:) !> Directory in which to search for source files character ( * ), intent ( in ) :: directory !> Scope to apply to the discovered sources, see [[fpm_model]] for enumeration integer , intent ( in ) :: scope !> Executable sources (fortran `program`s) are ignored unless `with_executables=.true.` logical , intent ( in ), optional :: with_executables !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) !> Whether to recursively search subdirectories, default is `.true.` logical , intent ( in ), optional :: recurse !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i logical , allocatable :: is_source (:), exclude_source (:) logical :: recurse_ type ( string_t ), allocatable :: file_names (:) type ( string_t ), allocatable :: src_file_names (:), f_ext (:) type ( string_t ), allocatable :: existing_src_files (:) type ( srcfile_t ), allocatable :: dir_sources (:) recurse_ = . true . if ( present ( recurse )) recurse_ = recurse ! Scan directory for sources call list_files ( directory , file_names , recurse = recurse_ ) if ( allocated ( sources )) then allocate ( existing_src_files ( size ( sources ))) do i = 1 , size ( sources ) existing_src_files ( i )% s = canon_path ( sources ( i )% file_name ) end do else allocate ( existing_src_files ( 0 )) end if ! Get legal fortran suffixes call list_fortran_suffixes ( f_ext , with_f_ext ) is_source = [(. not .( is_hidden_file ( basename ( file_names ( i )% s ))) . and . & . not .( canon_path ( file_names ( i )% s ) . in . existing_src_files ) . and . & ( str_ends_with ( lower ( file_names ( i )% s ), f_ext ) . or . & str_ends_with ( lower ( file_names ( i )% s ), c_suffixes ) ), i = 1 , size ( file_names ))] src_file_names = pack ( file_names , is_source ) allocate ( dir_sources ( size ( src_file_names ))) allocate ( exclude_source ( size ( src_file_names ))) do i = 1 , size ( src_file_names ) dir_sources ( i ) = parse_source ( src_file_names ( i )% s , with_f_ext , error ) if ( allocated ( error )) return dir_sources ( i )% unit_scope = scope allocate ( dir_sources ( i )% link_libraries ( 0 )) ! Exclude executables unless specified otherwise exclude_source ( i ) = ( dir_sources ( i )% unit_type == FPM_UNIT_PROGRAM ) if ( dir_sources ( i )% unit_type == FPM_UNIT_PROGRAM . and . & & present ( with_executables )) then if ( with_executables ) then exclude_source ( i ) = . false . end if end if end do if (. not . allocated ( sources )) then sources = pack ( dir_sources ,. not . exclude_source ) else sources = [ sources , pack ( dir_sources ,. not . exclude_source )] end if end subroutine add_sources_from_dir","tags":"","loc":"proc/add_sources_from_dir.html"},{"title":"new_library – Fortran-lang/fpm","text":"public subroutine new_library(self, table, error) Construct a new library configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( library_config_t ), intent(out) :: self Instance of the library configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_library ( self , table , error ) !> Instance of the library configuration type ( library_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"source-dir\" , self % source_dir , \"src\" ) call get_value ( table , \"build-script\" , self % build_script ) call get_list ( table , \"include-dir\" , self % include_dir , error ) if ( allocated ( error )) return ! Set default value of include-dir if not found in manifest if (. not . allocated ( self % include_dir )) then self % include_dir = [ string_t ( \"include\" )] end if end subroutine new_library","tags":"","loc":"proc/new_library.html"},{"title":"parse_c_source – Fortran-lang/fpm","text":"public function parse_c_source(c_filename, error) result(c_source) Parsing of c, cpp source files The following statements are recognised and parsed: #include preprocessor statement Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: c_filename type( error_t ), intent(out), allocatable :: error Return Value type( srcfile_t ) Source Code function parse_c_source ( c_filename , error ) result ( c_source ) character ( * ), intent ( in ) :: c_filename type ( srcfile_t ) :: c_source type ( error_t ), allocatable , intent ( out ) :: error integer :: fh , n_include , i , pass , stat type ( string_t ), allocatable :: file_lines (:) c_source % file_name = c_filename if ( str_ends_with ( lower ( c_filename ), \".c\" )) then c_source % unit_type = FPM_UNIT_CSOURCE else if ( str_ends_with ( lower ( c_filename ), \".h\" )) then c_source % unit_type = FPM_UNIT_CHEADER else if ( str_ends_with ( lower ( c_filename ), \".cpp\" )) then c_source % unit_type = FPM_UNIT_CPPSOURCE end if allocate ( c_source % modules_used ( 0 )) allocate ( c_source % modules_provided ( 0 )) allocate ( c_source % parent_modules ( 0 )) file_lines = read_lines ( c_filename ) ! Ignore empty files, returned as FPM_UNIT_UNKNOWN if ( len_trim ( file_lines ) < 1 ) then c_source % unit_type = FPM_UNIT_UNKNOWN return end if c_source % digest = fnv_1a ( file_lines ) do pass = 1 , 2 n_include = 0 file_loop : do i = 1 , size ( file_lines ) ! Process 'INCLUDE' statements if ( index ( adjustl ( lower ( file_lines ( i )% s )), '#include' ) == 1 . and . & index ( file_lines ( i )% s , '\"' ) > 0 ) then n_include = n_include + 1 if ( pass == 2 ) then c_source % include_dependencies ( n_include )% s = & & split_n ( file_lines ( i )% s , n = 2 , delims = '\"' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , c_filename , & 'unable to get c include file' , i , & file_lines ( i )% s , index ( file_lines ( i )% s , '\"' )) return end if end if end if end do file_loop if ( pass == 1 ) then allocate ( c_source % include_dependencies ( n_include )) end if end do end function parse_c_source","tags":"","loc":"proc/parse_c_source.html"},{"title":"parse_f_source – Fortran-lang/fpm","text":"public function parse_f_source(f_filename, error) result(f_source) Parsing of free-form fortran source files The following statements are recognised and parsed: Module / submodule / program declaration Module use statement include statement @note Note\n Intrinsic modules used by sources are not listed in\n the modules_used field of source objects. @note Note\n Submodules are treated as normal modules which use their\n corresponding parent modules. Parsing limitations Statements must not continued onto another line\n except for an only: list in the use statement. This is supported: use my_module , only : & my_var , my_function , my_subroutine This is NOT supported: use & my_module Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_filename type( error_t ), intent(out), allocatable :: error Return Value type( srcfile_t ) Source Code function parse_f_source ( f_filename , error ) result ( f_source ) character ( * ), intent ( in ) :: f_filename type ( srcfile_t ) :: f_source type ( error_t ), allocatable , intent ( out ) :: error logical :: inside_module , inside_interface , using , intrinsic_module integer :: stat integer :: fh , n_use , n_include , n_mod , n_parent , i , j , ic , pass type ( string_t ), allocatable :: file_lines (:), file_lines_lower (:) character (:), allocatable :: temp_string , mod_name , string_parts (:) if (. not . exists ( f_filename )) then call file_not_found_error ( error , f_filename ) return end if f_source % file_name = f_filename file_lines = read_lines_expanded ( f_filename ) ! for efficiency in parsing make a lowercase left-adjusted copy of the file ! Need a copy because INCLUDE (and #include) file arguments are case-sensitive file_lines_lower = file_lines do i = 1 , size ( file_lines_lower ) file_lines_lower ( i )% s = adjustl ( lower ( file_lines_lower ( i )% s )) enddo ! fnv_1a can only be applied to non-zero-length arrays if ( len_trim ( file_lines_lower ) > 0 ) f_source % digest = fnv_1a ( file_lines ) do pass = 1 , 2 n_use = 0 n_include = 0 n_mod = 0 n_parent = 0 inside_module = . false . inside_interface = . false . file_loop : do i = 1 , size ( file_lines_lower ) ! Skip comment lines and preprocessor directives if ( index ( file_lines_lower ( i )% s , '!' ) == 1 . or . & index ( file_lines_lower ( i )% s , '#' ) == 1 . or . & len_trim ( file_lines_lower ( i )% s ) < 1 ) then cycle end if ! Detect exported C-API via bind(C) if (. not . inside_interface . and . & parse_subsequence ( file_lines_lower ( i )% s , 'bind' , '(' , 'c' )) then do j = i , 1 , - 1 if ( index ( file_lines_lower ( j )% s , 'function' ) > 0 . or . & index ( file_lines_lower ( j )% s , 'subroutine' ) > 0 ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM exit end if if ( j > 1 ) then ic = index ( file_lines_lower ( j - 1 )% s , '!' ) if ( ic < 1 ) then ic = len ( file_lines_lower ( j - 1 )% s ) end if temp_string = trim ( file_lines_lower ( j - 1 )% s ( 1 : ic )) if ( index ( temp_string , '&' ) /= len ( temp_string )) then exit end if end if end do end if ! Skip lines that are continued: not statements if ( i > 1 ) then ic = index ( file_lines_lower ( i - 1 )% s , '!' ) if ( ic < 1 ) then ic = len ( file_lines_lower ( i - 1 )% s ) end if temp_string = trim ( file_lines_lower ( i - 1 )% s ( 1 : ic )) if ( len ( temp_string ) > 0 . and . index ( temp_string , '&' ) == len ( temp_string )) then cycle end if end if ! Detect beginning of interface block if ( index ( file_lines_lower ( i )% s , 'interface' ) == 1 & . or . parse_sequence ( file_lines_lower ( i )% s , 'abstract' , 'interface' )) then inside_interface = . true . cycle end if ! Detect end of interface block if ( parse_sequence ( file_lines_lower ( i )% s , 'end' , 'interface' )) then inside_interface = . false . cycle end if ! Process 'USE' statements call parse_use_statement ( f_filename , i , file_lines_lower ( i )% s , using , intrinsic_module , mod_name , error ) if ( allocated ( error )) return if ( using ) then ! Not a valid module name? if (. not . is_fortran_name ( mod_name )) cycle ! Valid intrinsic module: not a dependency if ( intrinsic_module ) cycle n_use = n_use + 1 if ( pass == 2 ) f_source % modules_used ( n_use )% s = mod_name cycle endif ! Process 'INCLUDE' statements ic = index ( file_lines_lower ( i )% s , 'include' ) if ( ic == 1 ) then ic = index ( lower ( file_lines ( i )% s ), 'include' ) if ( index ( adjustl ( file_lines ( i )% s ( ic + 7 :)), '\"' ) == 1 . or . & index ( adjustl ( file_lines ( i )% s ( ic + 7 :)), \"'\" ) == 1 ) then n_include = n_include + 1 if ( pass == 2 ) then f_source % include_dependencies ( n_include )% s = & & split_n ( file_lines ( i )% s , n = 2 , delims = \"'\" // '\"' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find include file name' , i , & file_lines ( i )% s ) return end if end if cycle end if end if ! Extract name of module if is module if ( index ( file_lines_lower ( i )% s , 'module ' ) == 1 ) then ! Remove any trailing comments ic = index ( file_lines_lower ( i )% s , '!' ) - 1 if ( ic < 1 ) then ic = len ( file_lines_lower ( i )% s ) end if temp_string = trim ( file_lines_lower ( i )% s ( 1 : ic )) ! R1405 module-stmt := \"MODULE\" module-name ! module-stmt has two space-delimited parts only ! (no line continuations) call split ( temp_string , string_parts , ' ' ) if ( size ( string_parts ) /= 2 ) then cycle end if mod_name = trim ( adjustl ( string_parts ( 2 ))) if ( scan ( mod_name , '=(&' ) > 0 ) then ! Ignore these cases: ! module & ! module =* ! module (i) cycle end if if (. not . is_fortran_name ( mod_name )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for module' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , mod_name )) return end if n_mod = n_mod + 1 if ( pass == 2 ) then f_source % modules_provided ( n_mod ) = string_t ( mod_name ) end if if ( f_source % unit_type == FPM_UNIT_UNKNOWN ) then f_source % unit_type = FPM_UNIT_MODULE end if if (. not . inside_module ) then inside_module = . true . else ! Must have missed an end module statement (can't assume a pure module) if ( f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if end if cycle end if ! Extract name of submodule if is submodule if ( index ( file_lines_lower ( i )% s , 'submodule' ) == 1 ) then mod_name = split_n ( file_lines_lower ( i )% s , n = 3 , delims = '()' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to get submodule name' , i , & file_lines_lower ( i )% s ) return end if if (. not . is_fortran_name ( mod_name )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for submodule' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , mod_name )) return end if n_mod = n_mod + 1 temp_string = split_n ( file_lines_lower ( i )% s , n = 2 , delims = '()' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to get submodule ancestry' , i , & file_lines_lower ( i )% s ) return end if if ( f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBMODULE end if n_use = n_use + 1 inside_module = . true . n_parent = n_parent + 1 if ( pass == 2 ) then if ( index ( temp_string , ':' ) > 0 ) then temp_string = temp_string ( index ( temp_string , ':' ) + 1 :) end if if (. not . is_fortran_name ( temp_string )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for submodule parent' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , temp_string )) return end if f_source % modules_used ( n_use )% s = temp_string f_source % parent_modules ( n_parent )% s = temp_string f_source % modules_provided ( n_mod )% s = mod_name end if cycle end if ! Detect if contains a program ! (no modules allowed after program def) if ( index ( file_lines_lower ( i )% s , 'program ' ) == 1 ) then temp_string = split_n ( file_lines_lower ( i )% s , n = 2 , delims = ' ' , stat = stat ) if ( stat == 0 ) then if ( scan ( temp_string , '=(' ) > 0 ) then ! Ignore: ! program =* ! program (i) =* cycle end if end if f_source % unit_type = FPM_UNIT_PROGRAM cycle end if ! Parse end module statement ! (to check for code outside of modules) if ( parse_sequence ( file_lines_lower ( i )% s , 'end' , 'module' ) . or . & parse_sequence ( file_lines_lower ( i )% s , 'end' , 'submodule' )) then inside_module = . false . cycle end if ! Any statements not yet parsed are assumed to be other code statements if (. not . inside_module . and . f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if end do file_loop ! If unable to parse end of module statement, then can't assume pure module ! (there could be non-module subprograms present) if ( inside_module . and . f_source % unit_type == FPM_UNIT_MODULE ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if if ( pass == 1 ) then allocate ( f_source % modules_used ( n_use )) allocate ( f_source % include_dependencies ( n_include )) allocate ( f_source % modules_provided ( n_mod )) allocate ( f_source % parent_modules ( n_parent )) end if end do end function parse_f_source","tags":"","loc":"proc/parse_f_source.html"},{"title":"parse_use_statement – Fortran-lang/fpm","text":"public subroutine parse_use_statement(f_filename, i, line, use_stmt, is_intrinsic, module_name, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_filename Current file name and line number (for error messaging) integer, intent(in) :: i character(len=*), intent(in) :: line The line being parsed. MUST BE preprocessed with trim(adjustl() logical, intent(out) :: use_stmt Does this line contain a use statement? logical, intent(out) :: is_intrinsic Is the module in this statement intrinsic? character(len=:), intent(out), allocatable :: module_name used module name type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine parse_use_statement ( f_filename , i , line , use_stmt , is_intrinsic , module_name , error ) !> Current file name and line number (for error messaging) character ( * ), intent ( in ) :: f_filename integer , intent ( in ) :: i !> The line being parsed. MUST BE preprocessed with trim(adjustl() character ( * ), intent ( in ) :: line !> Does this line contain a `use` statement? logical , intent ( out ) :: use_stmt !> Is the module in this statement intrinsic? logical , intent ( out ) :: is_intrinsic !> used module name character (:), allocatable , intent ( out ) :: module_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( 15 ), parameter :: INTRINSIC_NAMES ( * ) = & [ 'iso_c_binding ' , & 'iso_fortran_env' , & 'ieee_arithmetic' , & 'ieee_exceptions' , & 'ieee_features ' , & 'omp_lib ' ] character ( len = :), allocatable :: temp_string integer :: colons , intr , nonintr , j , stat logical :: has_intrinsic_name use_stmt = . false . is_intrinsic = . false . if ( len_trim ( line ) <= 0 ) return ! Quick check that the line is preprocessed if ( line ( 1 : 1 ) == ' ' ) then call fatal_error ( error , 'internal_error: source file line is not trim(adjustl()) on input to parse_use_statement' ) return end if ! 'use' should be the first string in the adjustl line use_stmt = index ( line , 'use ' ) == 1 . or . index ( line , 'use::' ) == 1 . or . index ( line , 'use,' ) == 1 if (. not . use_stmt ) return colons = index ( line , '::' ) nonintr = 0 intr = 0 have_colons : if ( colons > 3 ) then ! there may be an intrinsic/non-intrinsic spec nonintr = index ( line ( 1 : colons - 1 ), 'non_intrinsic' ) if ( nonintr == 0 ) intr = index ( line ( 1 : colons - 1 ), 'intrinsic' ) temp_string = split_n ( line , delims = ':' , n = 2 , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line , colons ) return end if module_name = split_n ( temp_string , delims = ' ,' , n = 1 , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line ) return end if else module_name = split_n ( line , n = 2 , delims = ' ,' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line ) return end if end if have_colons ! If declared intrinsic, check that it is true has_intrinsic_name = any ([( index ( module_name , trim ( INTRINSIC_NAMES ( j ))) > 0 , & j = 1 , size ( INTRINSIC_NAMES ))]) if ( intr > 0 . and . . not . has_intrinsic_name ) then ! An intrinsic module was not found. Its name could be in the next line, ! in which case, we just skip this check. The compiler will do the job if the name is invalid. ! Module name was not read: it's in the next line if ( index ( module_name , '&' ) <= 0 ) then call file_parse_error ( error , f_filename , & 'module ' // module_name // ' is declared intrinsic but it is not ' , i , & line ) return endif endif ! Should we treat this as an intrinsic module is_intrinsic = nonintr == 0 . and . & ! not declared non-intrinsic ( intr > 0 . or . has_intrinsic_name ) end subroutine parse_use_statement","tags":"","loc":"proc/parse_use_statement.html"},{"title":"bad_name_error – Fortran-lang/fpm","text":"public function bad_name_error(error, label, name) Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: label Error message label to add to message character(len=*), intent(in) :: name name value to check Return Value logical Source Code function bad_name_error ( error , label , name ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message label to add to message character ( len =* ), intent ( in ) :: label !> name value to check character ( len =* ), intent ( in ) :: name logical :: bad_name_error if (. not . is_fortran_name ( to_fortran_name ( name ))) then bad_name_error = . true . allocate ( error ) error % message = 'manifest file syntax error: ' // label // ' name must be composed only of & &alphanumerics, \"-\" and \"_\" and start with a letter ::' // name else bad_name_error = . false . endif end function bad_name_error","tags":"","loc":"proc/bad_name_error.html"},{"title":"fatal_error – Fortran-lang/fpm","text":"public subroutine fatal_error(error, message) Generic fatal runtime error Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: message Error message Source Code subroutine fatal_error ( error , message ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message character ( len =* ), intent ( in ) :: message allocate ( error ) error % message = message end subroutine fatal_error","tags":"","loc":"proc/fatal_error.html"},{"title":"file_not_found_error – Fortran-lang/fpm","text":"public subroutine file_not_found_error(error, file_name) Error created when a file is missing or not found Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: file_name Name of the missing file Source Code subroutine file_not_found_error ( error , file_name ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Name of the missing file character ( len =* ), intent ( in ) :: file_name allocate ( error ) error % message = \"'\" // file_name // \"' could not be found, check if the file exists\" end subroutine file_not_found_error","tags":"","loc":"proc/file_not_found_error.html"},{"title":"file_parse_error – Fortran-lang/fpm","text":"public subroutine file_parse_error(error, file_name, message, line_num, line_string, line_col) Error created when file parsing fails Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: file_name Name of file character(len=*), intent(in) :: message Parse error message integer, intent(in), optional :: line_num Line number of parse error character(len=*), intent(in), optional :: line_string Line context string integer, intent(in), optional :: line_col Line context column Source Code subroutine file_parse_error ( error , file_name , message , line_num , & line_string , line_col ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Name of file character ( len =* ), intent ( in ) :: file_name !> Parse error message character ( len =* ), intent ( in ) :: message !> Line number of parse error integer , intent ( in ), optional :: line_num !> Line context string character ( len =* ), intent ( in ), optional :: line_string !> Line context column integer , intent ( in ), optional :: line_col character ( 50 ) :: temp_string allocate ( error ) error % message = 'Parse error: ' // message // new_line ( 'a' ) error % message = error % message // file_name if ( present ( line_num )) then write ( temp_string , '(I0)' ) line_num error % message = error % message // ':' // trim ( temp_string ) end if if ( present ( line_col )) then if ( line_col > 0 ) then write ( temp_string , '(I0)' ) line_col error % message = error % message // ':' // trim ( temp_string ) end if end if if ( present ( line_string )) then error % message = error % message // new_line ( 'a' ) error % message = error % message // ' | ' // line_string if ( present ( line_col )) then if ( line_col > 0 ) then error % message = error % message // new_line ( 'a' ) error % message = error % message // ' | ' // repeat ( ' ' , line_col - 1 ) // '^' end if end if end if end subroutine file_parse_error","tags":"","loc":"proc/file_parse_error.html"},{"title":"fpm_stop – Fortran-lang/fpm","text":"public subroutine fpm_stop(value, message) Arguments Type Intent Optional Attributes Name integer, intent(in) :: value value to use on STOP character(len=*), intent(in) :: message Error message Source Code subroutine fpm_stop ( value , message ) ! TODO: if verbose mode, call ERROR STOP instead of STOP ! TODO: if M_escape is used, add color ! to work with older compilers might need a case statement for values !> value to use on STOP integer , intent ( in ) :: value !> Error message character ( len =* ), intent ( in ) :: message integer :: iostat if ( message /= '' ) then flush ( unit = stderr , iostat = iostat ) flush ( unit = stdout , iostat = iostat ) if ( value > 0 ) then write ( stderr , '(\" \",a)' ) trim ( message ) else write ( stderr , '(\" \",a)' ) trim ( message ) endif flush ( unit = stderr , iostat = iostat ) endif stop value end subroutine fpm_stop","tags":"","loc":"proc/fpm_stop.html"},{"title":"syntax_error – Fortran-lang/fpm","text":"public subroutine syntax_error(error, message) Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: message Error message Source Code subroutine syntax_error ( error , message ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message character ( len =* ), intent ( in ) :: message allocate ( error ) error % message = message end subroutine syntax_error","tags":"","loc":"proc/syntax_error.html"},{"title":"regex_version_from_text – Fortran-lang/fpm","text":"public function regex_version_from_text(text, what, error) result(ver) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: text character(len=*), intent(in) :: what type( error_t ), intent(out), allocatable :: error Return Value type( string_t ) Source Code type ( string_t ) function regex_version_from_text ( text , what , error ) result ( ver ) character ( * ), intent ( in ) :: text character ( * ), intent ( in ) :: what type ( error_t ), allocatable , intent ( out ) :: error integer :: ire , length if ( len_trim ( text ) <= 0 ) then call syntax_error ( error , 'cannot retrieve ' // what // ' version: empty input string' ) return end if ! Extract 3-sized version \"1.0.4\" ire = regex ( text , '\\d+\\.\\d+\\.\\d+' , length = length ) if ( ire > 0 . and . length > 0 ) then ! Parse version into the object (this should always work) ver = string_t ( text ( ire : ire + length - 1 )) else ! Try 2-sized version \"1.0\" ire = regex ( text , '\\d+\\.\\d+' , length = length ) if ( ire > 0 . and . length > 0 ) then ver = string_t ( text ( ire : ire + length - 1 )) else call syntax_error ( error , 'cannot retrieve ' // what // ' version.' ) end if end if end function regex_version_from_text","tags":"","loc":"proc/regex_version_from_text.html"},{"title":"new_version – Fortran-lang/fpm","text":"public interface new_version Module Procedures private subroutine new_version_from_string(self, string, error) Create a new version from a string Arguments Type Intent Optional Attributes Name type( version_t ), intent(out) :: self Instance of the versioning data character(len=*), intent(in) :: string String describing the version information type( error_t ), intent(out), allocatable :: error Error handling private subroutine new_version_from_int(self, num) Create a new version from a string Arguments Type Intent Optional Attributes Name type( version_t ), intent(out) :: self Instance of the versioning data integer, intent(in) :: num (:) Subversion numbers to define version data","tags":"","loc":"interface/new_version.html"},{"title":"new_executable – Fortran-lang/fpm","text":"public subroutine new_executable(self, table, error) Construct a new executable configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( executable_config_t ), intent(out) :: self Instance of the executable configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_executable ( self , table , error ) !> Instance of the executable configuration type ( executable_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve executable name\" ) return end if if ( bad_name_error ( error , 'executable' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"app\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_executable","tags":"","loc":"proc/new_executable.html"},{"title":"cmd_update – Fortran-lang/fpm","text":"public subroutine cmd_update(settings) Entry point for the update subcommand Arguments Type Intent Optional Attributes Name type( fpm_update_settings ), intent(in) :: settings Representation of the command line arguments Source Code subroutine cmd_update ( settings ) !> Representation of the command line arguments type ( fpm_update_settings ), intent ( in ) :: settings type ( package_config_t ) :: package type ( dependency_tree_t ) :: deps type ( error_t ), allocatable :: error integer :: ii character ( len = :), allocatable :: cache call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) if (. not . exists ( \"build\" )) then call mkdir ( \"build\" ) call filewrite ( join_path ( \"build\" , \".gitignore\" ),[ \"*\" ]) end if cache = join_path ( \"build\" , \"cache.toml\" ) if ( settings % clean ) call delete_file ( cache ) call new_dependency_tree ( deps , cache = cache , & verbosity = merge ( 2 , 1 , settings % verbose )) call deps % add ( package , error ) call handle_error ( error ) ! Force-update all dependencies if `--clean` if ( settings % clean ) then do ii = 1 , deps % ndep deps % dep ( ii )% update = . true . end do end if if ( settings % fetch_only ) return if ( size ( settings % name ) == 0 ) then call deps % update ( error ) call handle_error ( error ) else do ii = 1 , size ( settings % name ) call deps % update ( trim ( settings % name ( ii )), error ) call handle_error ( error ) end do end if if ( len_trim ( settings % dump ) > 0 ) then call deps % dump ( trim ( settings % dump ), error , json = name_is_json ( trim ( settings % dump ))) call handle_error ( error ) end if end subroutine cmd_update","tags":"","loc":"proc/cmd_update.html"},{"title":"new_example – Fortran-lang/fpm","text":"public subroutine new_example(self, table, error) Construct a new example configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( example_config_t ), intent(out) :: self Instance of the example configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_example ( self , table , error ) !> Instance of the example configuration type ( example_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve example name\" ) return end if if ( bad_name_error ( error , 'example' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"example\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_example","tags":"","loc":"proc/new_example.html"},{"title":"ar_is_same – Fortran-lang/fpm","text":"public function ar_is_same(this, that) Check that two archiver_t objects are equal\nAll checks passed! Type Bound archiver_t Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Source Code logical function ar_is_same ( this , that ) class ( archiver_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that ar_is_same = . false . select type ( other => that ) type is ( archiver_t ) if (. not .( this % ar == other % ar )) return if (. not .( this % use_response_file . eqv . other % use_response_file )) return if (. not .( this % echo . eqv . other % echo )) return if (. not .( this % verbose . eqv . other % verbose )) return class default ! Not the same type return end select !> All checks passed! ar_is_same = . true . end function ar_is_same","tags":"","loc":"proc/ar_is_same.html"},{"title":"check_compiler – Fortran-lang/fpm","text":"public function check_compiler(compiler, expected) result(match) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler character(len=*), intent(in) :: expected Return Value logical Source Code function check_compiler ( compiler , expected ) result ( match ) character ( len =* ), intent ( in ) :: compiler character ( len =* ), intent ( in ) :: expected logical :: match match = compiler == expected if (. not . match ) then match = index ( basename ( compiler ), expected ) > 0 end if end function check_compiler","tags":"","loc":"proc/check_compiler.html"},{"title":"check_fortran_source_runs – Fortran-lang/fpm","text":"public function check_fortran_source_runs(self, input) result(success) Run a single-source Fortran program using the current compiler\nCompile a Fortran object\nCreate temporary source file\nWrite contents\nCompile and link program\nRun and retrieve exit code Successful exit on 0 exit code Delete files Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Program Source Return Value logical Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: exe character(len=:), public, allocatable :: logf character(len=:), public, allocatable :: object character(len=:), public, allocatable :: source integer, public :: stat integer, public :: unit Source Code logical function check_fortran_source_runs ( self , input ) result ( success ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Program Source character ( len =* ), intent ( in ) :: input integer :: stat , unit character (:), allocatable :: source , object , logf , exe success = . false . !> Create temporary source file exe = get_temp_filename () source = exe // '.f90' object = exe // '.o' logf = exe // '.log' open ( newunit = unit , file = source , action = 'readwrite' , iostat = stat ) if ( stat /= 0 ) return !> Write contents write ( unit , * ) input close ( unit ) !> Compile and link program call self % compile_fortran ( source , object , self % get_default_flags ( release = . false .), logf , stat ) if ( stat == 0 ) & call self % link ( exe , self % get_default_flags ( release = . false .) // \" \" // object , logf , stat ) !> Run and retrieve exit code if ( stat == 0 ) & call run ( exe , echo = . false ., exitstat = stat , verbose = . false ., redirect = logf ) !> Successful exit on 0 exit code success = stat == 0 !> Delete files open ( newunit = unit , file = source , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = object , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = logf , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = exe , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) end function check_fortran_source_runs","tags":"","loc":"proc/check_fortran_source_runs.html"},{"title":"compiler_is_same – Fortran-lang/fpm","text":"public function compiler_is_same(this, that) Check that two compiler_t objects are equal\nAll checks passed! Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Source Code logical function compiler_is_same ( this , that ) class ( compiler_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that compiler_is_same = . false . select type ( other => that ) type is ( compiler_t ) if (. not .( this % id == other % id )) return if (. not .( this % fc == other % fc )) return if (. not .( this % cc == other % cc )) return if (. not .( this % cxx == other % cxx )) return if (. not .( this % echo . eqv . other % echo )) return if (. not .( this % verbose . eqv . other % verbose )) return class default ! Not the same type return end select !> All checks passed! compiler_is_same = . true . end function compiler_is_same","tags":"","loc":"proc/compiler_is_same.html"},{"title":"compiler_name – Fortran-lang/fpm","text":"public pure function compiler_name(self) result(name) Return a compiler name string Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string Source Code pure function compiler_name ( self ) result ( name ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: name select case ( self % id ) case ( id_gcc ); name = \"gfortran\" case ( id_f95 ); name = \"f95\" case ( id_caf ); name = \"caf\" case ( id_intel_classic_nix ); name = \"ifort\" case ( id_intel_classic_mac ); name = \"ifort\" case ( id_intel_classic_windows ); name = \"ifort\" case ( id_intel_llvm_nix ); name = \"ifx\" case ( id_intel_llvm_windows ); name = \"ifx\" case ( id_intel_llvm_unknown ); name = \"ifx\" case ( id_pgi ); name = \"pgfortran\" case ( id_nvhpc ); name = \"nvfortran\" case ( id_nag ); name = \"nagfor\" case ( id_flang ); name = \"flang\" case ( id_flang_new ); name = \"flang-new\" case ( id_f18 ); name = \"f18\" case ( id_ibmxl ); name = \"xlf90\" case ( id_cray ); name = \"crayftn\" case ( id_lahey ); name = \"lfc\" case ( id_lfortran ); name = \"lFortran\" case default ; name = \"invalid/unknown\" end select end function compiler_name","tags":"","loc":"proc/compiler_name.html"},{"title":"debug_archiver – Fortran-lang/fpm","text":"public pure function debug_archiver(self) result(repr) String representation of an archiver object Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(in) :: self Instance of the archiver object Return Value character(len=:), allocatable Representation as string Source Code pure function debug_archiver ( self ) result ( repr ) !> Instance of the archiver object type ( archiver_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: repr repr = 'ar=\"' // self % ar // '\"' end function debug_archiver","tags":"","loc":"proc/debug_archiver.html"},{"title":"debug_compiler – Fortran-lang/fpm","text":"public pure function debug_compiler(self) result(repr) String representation of a compiler object Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string Source Code pure function debug_compiler ( self ) result ( repr ) !> Instance of the compiler object type ( compiler_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: repr repr = 'fc=\"' // self % fc // '\", cc=\"' // self % cc // '\"' end function debug_compiler","tags":"","loc":"proc/debug_compiler.html"},{"title":"enumerate_libraries – Fortran-lang/fpm","text":"public function enumerate_libraries(self, prefix, libs) result(r) Enumerate libraries, based on compiler and platform Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: prefix type( string_t ), intent(in) :: libs (:) Return Value character(len=:), allocatable Source Code function enumerate_libraries ( self , prefix , libs ) result ( r ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: prefix type ( string_t ), intent ( in ) :: libs (:) character ( len = :), allocatable :: r if ( self % id == id_intel_classic_windows . or . & self % id == id_intel_llvm_windows ) then r = prefix // \" \" // string_cat ( libs , \".lib \" ) // \".lib\" else r = prefix // \" -l\" // string_cat ( libs , \" -l\" ) end if end function enumerate_libraries","tags":"","loc":"proc/enumerate_libraries.html"},{"title":"get_compiler_id – Fortran-lang/fpm","text":"public function get_compiler_id(compiler) result(id) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler Return Value integer(kind=compiler_enum) Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: command character(len=:), public, allocatable :: full_command character(len=:), public, allocatable :: full_command_parts (:) integer, public :: io character(len=:), public, allocatable :: output integer, public :: stat Source Code function get_compiler_id ( compiler ) result ( id ) character ( len =* ), intent ( in ) :: compiler integer ( kind = compiler_enum ) :: id character ( len = :), allocatable :: full_command , full_command_parts (:), command , output integer :: stat , io ! Check whether we are dealing with an MPI compiler wrapper first if ( check_compiler ( compiler , \"mpifort\" ) & & . or . check_compiler ( compiler , \"mpif90\" ) & & . or . check_compiler ( compiler , \"mpif77\" )) then output = get_temp_filename () call run ( compiler // \" -show > \" // output // \" 2>&1\" , & & echo = . false ., exitstat = stat ) if ( stat == 0 ) then open ( file = output , newunit = io , iostat = stat ) if ( stat == 0 ) call getline ( io , full_command , stat ) close ( io , iostat = stat ) ! If we get a command from the wrapper, we will try to identify it call split ( full_command , full_command_parts , delimiters = ' ' ) if ( size ( full_command_parts ) > 0 ) then command = trim ( full_command_parts ( 1 )) endif if ( allocated ( command )) then id = get_id ( command ) if ( id /= id_unknown ) return end if end if end if id = get_id ( compiler ) end function get_compiler_id","tags":"","loc":"proc/get_compiler_id.html"},{"title":"get_default_flags – Fortran-lang/fpm","text":"public function get_default_flags(self, release) result(flags) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self logical, intent(in) :: release Return Value character(len=:), allocatable Source Code function get_default_flags ( self , release ) result ( flags ) class ( compiler_t ), intent ( in ) :: self logical , intent ( in ) :: release character ( len = :), allocatable :: flags if ( release ) then call get_release_compile_flags ( self % id , flags ) else call get_debug_compile_flags ( self % id , flags ) end if end function get_default_flags","tags":"","loc":"proc/get_default_flags.html"},{"title":"get_feature_flag – Fortran-lang/fpm","text":"public function get_feature_flag(self, feature) result(flags) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: feature Return Value character(len=:), allocatable Source Code function get_feature_flag ( self , feature ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: feature character ( len = :), allocatable :: flags flags = \"\" select case ( feature ) case ( \"no-implicit-typing\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_no_implicit_typing case ( id_nag ) flags = flag_nag_no_implicit_typing case ( id_cray ) flags = flag_cray_no_implicit_typing end select case ( \"implicit-typing\" ) select case ( self % id ) case ( id_cray ) flags = flag_cray_implicit_typing case ( id_lfortran ) flags = flag_lfortran_implicit_typing end select case ( \"no-implicit-external\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_no_implicit_external end select case ( \"implicit-external\" ) select case ( self % id ) case ( id_lfortran ) flags = flag_lfortran_implicit_external end select case ( \"free-form\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_free_form case ( id_pgi , id_nvhpc , id_flang ) flags = flag_pgi_free_form case ( id_nag ) flags = flag_nag_free_form case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , & & id_intel_llvm_unknown ) flags = flag_intel_free_form case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = flag_intel_free_form_win case ( id_cray ) flags = flag_cray_free_form end select case ( \"fixed-form\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_fixed_form case ( id_pgi , id_nvhpc , id_flang ) flags = flag_pgi_fixed_form case ( id_nag ) flags = flag_nag_fixed_form case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , & & id_intel_llvm_unknown ) flags = flag_intel_fixed_form case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = flag_intel_fixed_form_win case ( id_cray ) flags = flag_cray_fixed_form case ( id_lfortran ) flags = flag_lfortran_fixed_form end select case ( \"default-form\" ) continue case default error stop \"Unknown feature '\" // feature // \"'\" end select end function get_feature_flag","tags":"","loc":"proc/get_feature_flag.html"},{"title":"get_id – Fortran-lang/fpm","text":"public function get_id(compiler) result(id) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler Return Value integer(kind=compiler_enum) Source Code function get_id ( compiler ) result ( id ) character ( len =* ), intent ( in ) :: compiler integer ( kind = compiler_enum ) :: id if ( check_compiler ( compiler , \"gfortran\" )) then id = id_gcc return end if if ( check_compiler ( compiler , \"f95\" )) then id = id_f95 return end if if ( check_compiler ( compiler , \"caf\" )) then id = id_caf return end if if ( check_compiler ( compiler , \"ifort\" )) then select case ( get_os_type ()) case default id = id_intel_classic_nix case ( OS_MACOS ) id = id_intel_classic_mac case ( OS_WINDOWS , OS_CYGWIN ) id = id_intel_classic_windows end select return end if if ( check_compiler ( compiler , \"ifx\" )) then select case ( get_os_type ()) case default id = id_intel_llvm_nix case ( OS_WINDOWS , OS_CYGWIN ) id = id_intel_llvm_windows end select return end if if ( check_compiler ( compiler , \"nvfortran\" )) then id = id_nvhpc return end if if ( check_compiler ( compiler , \"pgfortran\" ) & & . or . check_compiler ( compiler , \"pgf90\" ) & & . or . check_compiler ( compiler , \"pgf95\" )) then id = id_pgi return end if if ( check_compiler ( compiler , \"nagfor\" )) then id = id_nag return end if if ( check_compiler ( compiler , \"flang-new\" )) then id = id_flang_new return end if if ( check_compiler ( compiler , \"f18\" )) then id = id_f18 return end if if ( check_compiler ( compiler , \"flang\" )) then id = id_flang return end if if ( check_compiler ( compiler , \"xlf90\" )) then id = id_ibmxl return end if if ( check_compiler ( compiler , \"crayftn\" )) then id = id_cray return end if if ( check_compiler ( compiler , \"lfc\" )) then id = id_lahey return end if if ( check_compiler ( compiler , \"lfortran\" )) then id = id_lfortran return end if id = id_unknown end function get_id","tags":"","loc":"proc/get_id.html"},{"title":"get_include_flag – Fortran-lang/fpm","text":"public function get_include_flag(self, path) result(flags) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function get_include_flag ( self , path ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: flags select case ( self % id ) case default flags = \"-I \" // path case ( id_caf , id_gcc , id_f95 , id_cray , id_nvhpc , id_pgi , & & id_flang , id_flang_new , id_f18 , & & id_intel_classic_nix , id_intel_classic_mac , & & id_intel_llvm_nix , id_lahey , id_nag , id_ibmxl , & & id_lfortran ) flags = \"-I \" // path case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = \"/I\" // path end select end function get_include_flag","tags":"","loc":"proc/get_include_flag.html"},{"title":"get_macros – Fortran-lang/fpm","text":"public function get_macros(id, macros_list, version) result(macros) This function will parse and read the macros list and\nreturn them as defined flags.\nSet macro defintion symbol on the basis of compiler used\nCheck if macros are not allocated.\nSplit the macro name and value. Check if the value of macro starts with ‘{’ character. Check if the value of macro ends with ‘}’ character. Check if the string contains “version” as substring. These conditions are placed in order to ensure proper spacing between the macros. Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id type( string_t ), intent(in), allocatable :: macros_list (:) character(len=:), intent(in), allocatable :: version Return Value character(len=:), allocatable Variables Type Visibility Attributes Name Initial integer, public :: i character(len=:), public, allocatable :: macro_definition_symbol character(len=:), public, allocatable :: valued_macros (:) Source Code function get_macros ( id , macros_list , version ) result ( macros ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( in ) :: version type ( string_t ), allocatable , intent ( in ) :: macros_list (:) character ( len = :), allocatable :: macros character ( len = :), allocatable :: macro_definition_symbol character (:), allocatable :: valued_macros (:) integer :: i if (. not . allocated ( macros_list )) then macros = \"\" return end if !> Set macro defintion symbol on the basis of compiler used select case ( id ) case default macro_definition_symbol = \" -D\" case ( id_intel_classic_windows , id_intel_llvm_windows ) macro_definition_symbol = \" /D\" end select !> Check if macros are not allocated. if (. not . allocated ( macros )) then macros = \"\" end if do i = 1 , size ( macros_list ) !> Split the macro name and value. call split ( macros_list ( i )% s , valued_macros , delimiters = \"=\" ) if ( size ( valued_macros ) > 1 ) then !> Check if the value of macro starts with '{' character. if ( str_begins_with_str ( trim ( valued_macros ( size ( valued_macros ))), \"{\" )) then !> Check if the value of macro ends with '}' character. if ( str_ends_with ( trim ( valued_macros ( size ( valued_macros ))), \"}\" )) then !> Check if the string contains \"version\" as substring. if ( index ( valued_macros ( size ( valued_macros )), \"version\" ) /= 0 ) then !> These conditions are placed in order to ensure proper spacing between the macros. macros = macros // macro_definition_symbol // trim ( valued_macros ( 1 )) // '=' // version cycle end if end if end if end if macros = macros // macro_definition_symbol // macros_list ( i )% s end do end function get_macros","tags":"","loc":"proc/get_macros.html"},{"title":"get_module_flag – Fortran-lang/fpm","text":"public function get_module_flag(self, path) result(flags) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function get_module_flag ( self , path ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: flags select case ( self % id ) case default flags = \"-module \" // path case ( id_caf , id_gcc , id_f95 , id_cray , id_lfortran ) flags = \"-J \" // path case ( id_nvhpc , id_pgi , id_flang ) flags = \"-module \" // path case ( id_flang_new , id_f18 ) flags = \"-module-dir \" // path case ( id_intel_classic_nix , id_intel_classic_mac , & & id_intel_llvm_nix ) flags = \"-module \" // path case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = \"/module:\" // path case ( id_lahey ) flags = \"-M \" // path case ( id_nag ) flags = \"-mdir \" // path case ( id_ibmxl ) flags = \"-qmoddir \" // path end select end function get_module_flag","tags":"","loc":"proc/get_module_flag.html"},{"title":"is_gnu – Fortran-lang/fpm","text":"public pure function is_gnu(self) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical Source Code pure logical function is_gnu ( self ) class ( compiler_t ), intent ( in ) :: self is_gnu = any ( self % id == [ id_f95 , id_gcc , id_caf ]) end function is_gnu","tags":"","loc":"proc/is_gnu.html"},{"title":"is_intel – Fortran-lang/fpm","text":"public pure function is_intel(self) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical Source Code pure logical function is_intel ( self ) class ( compiler_t ), intent ( in ) :: self is_intel = any ( self % id == [ id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows , & id_intel_llvm_nix , id_intel_llvm_windows , id_intel_llvm_unknown ]) end function is_intel","tags":"","loc":"proc/is_intel.html"},{"title":"is_unknown – Fortran-lang/fpm","text":"public pure function is_unknown(self) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical Source Code pure function is_unknown ( self ) class ( compiler_t ), intent ( in ) :: self logical :: is_unknown is_unknown = self % id == id_unknown end function is_unknown","tags":"","loc":"proc/is_unknown.html"},{"title":"with_qp – Fortran-lang/fpm","text":"public function with_qp(self) Check if the current compiler supports 128-bit real precision Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical Source Code logical function with_qp ( self ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self with_qp = self % check_fortran_source_runs & ( 'if (selected_real_kind(33) == -1) stop 1; end' ) end function with_qp","tags":"","loc":"proc/with_qp.html"},{"title":"with_xdp – Fortran-lang/fpm","text":"public function with_xdp(self) Check if the current compiler supports 80-bit “extended” real precision Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical Source Code logical function with_xdp ( self ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self with_xdp = self % check_fortran_source_runs & ( 'if (any(selected_real_kind(18) == [-1, selected_real_kind(33)])) stop 1; end' ) end function with_xdp","tags":"","loc":"proc/with_xdp.html"},{"title":"compile_c – Fortran-lang/fpm","text":"public subroutine compile_c(self, input, output, args, log_file, stat) Compile a C object Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Source Code subroutine compile_c ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % cc // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_c","tags":"","loc":"proc/compile_c.html"},{"title":"compile_cpp – Fortran-lang/fpm","text":"public subroutine compile_cpp(self, input, output, args, log_file, stat) Compile a CPP object Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Source Code subroutine compile_cpp ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % cxx // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_cpp","tags":"","loc":"proc/compile_cpp.html"},{"title":"compile_fortran – Fortran-lang/fpm","text":"public subroutine compile_fortran(self, input, output, args, log_file, stat) Compile a Fortran object Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Source Code subroutine compile_fortran ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % fc // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_fortran","tags":"","loc":"proc/compile_fortran.html"},{"title":"compiler_dump – Fortran-lang/fpm","text":"public subroutine compiler_dump(self, table, error) Dump dependency to toml table Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ierr Source Code subroutine compiler_dump ( self , table , error ) !> Instance of the serializable object class ( compiler_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_value ( table , \"id\" , self % id , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"fc\" , self % fc , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"cc\" , self % cc , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"cxx\" , self % cxx , error , 'compiler_t' ) if ( allocated ( error )) return call set_value ( table , \"echo\" , self % echo , error , 'compiler_t' ) if ( allocated ( error )) return call set_value ( table , \"verbose\" , self % verbose , error , 'compiler_t' ) if ( allocated ( error )) return end subroutine compiler_dump","tags":"","loc":"proc/compiler_dump.html"},{"title":"compiler_load – Fortran-lang/fpm","text":"public subroutine compiler_load(self, table, error) Read dependency from toml table (no checks made at this stage) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine compiler_load ( self , table , error ) !> Instance of the serializable object class ( compiler_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"id\" , self % id , error , 'compiler_t' ) if ( allocated ( error )) return call get_value ( table , \"fc\" , self % fc ) call get_value ( table , \"cc\" , self % cc ) call get_value ( table , \"cxx\" , self % cxx ) call get_value ( table , \"echo\" , self % echo , error , 'compiler_t' ) if ( allocated ( error )) return call get_value ( table , \"verbose\" , self % verbose , error , 'compiler_t' ) if ( allocated ( error )) return end subroutine compiler_load","tags":"","loc":"proc/compiler_load.html"},{"title":"dump_to_toml – Fortran-lang/fpm","text":"public subroutine dump_to_toml(self, table, error) Dump dependency to toml table Path to archiver Type Bound archiver_t Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( archiver_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Path to archiver call set_string ( table , \"ar\" , self % ar , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"use-response-file\" , self % use_response_file , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"echo\" , self % echo , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"verbose\" , self % verbose , error , 'archiver_t' ) if ( allocated ( error )) return end subroutine dump_to_toml","tags":"","loc":"proc/dump_to_toml~8.html"},{"title":"get_debug_compile_flags – Fortran-lang/fpm","text":"public subroutine get_debug_compile_flags(id, flags) Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(out), allocatable :: flags Source Code subroutine get_debug_compile_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( out ) :: flags select case ( id ) case default flags = \"\" case ( id_caf ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & flag_gnu_backtrace case ( id_gcc ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & flag_gnu_backtrace // & flag_gnu_coarray case ( id_f95 ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & ' -Wno-maybe-uninitialized -Wno-uninitialized' // & flag_gnu_backtrace case ( id_nvhpc ) flags = & flag_pgi_warn // & flag_pgi_backslash // & flag_pgi_check // & flag_pgi_traceback case ( id_ibmxl ) flags = & flag_ibmxl_backslash case ( id_intel_classic_nix ) flags = & flag_intel_warn // & flag_intel_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_classic_mac ) flags = & flag_intel_warn // & flag_intel_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_classic_windows ) flags = & flag_intel_warn_win // & flag_intel_check_win // & flag_intel_limit_win // & flag_intel_debug_win // & flag_intel_byterecl_win // & flag_intel_backtrace_win case ( id_intel_llvm_nix ) flags = & flag_intel_warn // & flag_intel_llvm_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_llvm_windows ) flags = & flag_intel_warn_win // & flag_intel_check_win // & flag_intel_limit_win // & flag_intel_debug_win // & flag_intel_byterecl_win case ( id_nag ) flags = & flag_nag_debug // & flag_nag_check // & flag_nag_backtrace // & flag_nag_coarray // & flag_nag_pic case ( id_lfortran ) flags = \"\" end select end subroutine get_debug_compile_flags","tags":"","loc":"proc/get_debug_compile_flags.html"},{"title":"get_default_c_compiler – Fortran-lang/fpm","text":"public subroutine get_default_c_compiler(f_compiler, c_compiler) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_compiler character(len=:), intent(out), allocatable :: c_compiler Variables Type Visibility Attributes Name Initial integer(kind=compiler_enum), public :: id Source Code subroutine get_default_c_compiler ( f_compiler , c_compiler ) character ( len =* ), intent ( in ) :: f_compiler character ( len = :), allocatable , intent ( out ) :: c_compiler integer ( compiler_enum ) :: id id = get_compiler_id ( f_compiler ) select case ( id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows ) c_compiler = 'icc' case ( id_intel_llvm_nix , id_intel_llvm_windows ) c_compiler = 'icx' case ( id_flang , id_flang_new , id_f18 ) c_compiler = 'clang' case ( id_ibmxl ) c_compiler = 'xlc' case ( id_lfortran ) c_compiler = 'cc' case ( id_gcc ) c_compiler = 'gcc' case default ! Fall-back to using Fortran compiler c_compiler = f_compiler end select end subroutine get_default_c_compiler","tags":"","loc":"proc/get_default_c_compiler.html"},{"title":"get_default_cxx_compiler – Fortran-lang/fpm","text":"public subroutine get_default_cxx_compiler(f_compiler, cxx_compiler) Get C++ Compiler. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_compiler character(len=:), intent(out), allocatable :: cxx_compiler Variables Type Visibility Attributes Name Initial integer(kind=compiler_enum), public :: id Source Code subroutine get_default_cxx_compiler ( f_compiler , cxx_compiler ) character ( len =* ), intent ( in ) :: f_compiler character ( len = :), allocatable , intent ( out ) :: cxx_compiler integer ( compiler_enum ) :: id id = get_compiler_id ( f_compiler ) select case ( id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows ) cxx_compiler = 'icpc' case ( id_intel_llvm_nix , id_intel_llvm_windows ) cxx_compiler = 'icpx' case ( id_flang , id_flang_new , id_f18 ) cxx_compiler = 'clang++' case ( id_ibmxl ) cxx_compiler = 'xlc++' case ( id_lfortran ) cxx_compiler = 'cc' case ( id_gcc ) cxx_compiler = 'g++' case default ! Fall-back to using Fortran compiler cxx_compiler = f_compiler end select end subroutine get_default_cxx_compiler","tags":"","loc":"proc/get_default_cxx_compiler.html"},{"title":"get_main_flags – Fortran-lang/fpm","text":"public subroutine get_main_flags(self, language, flags) Get special flags for the main linker Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: language character(len=:), intent(out), allocatable :: flags Source Code subroutine get_main_flags ( self , language , flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: language character ( len = :), allocatable , intent ( out ) :: flags flags = \"\" select case ( language ) case ( \"fortran\" ) flags = \"\" case ( \"c\" ) ! If the main program is on a C/C++ source, the Intel Fortran compiler requires option ! -nofor-main to avoid \"duplicate main\" errors. ! https://stackoverflow.com/questions/36221612/p3dfft-compilation-ifort-compiler-error-multiple-definiton-of-main select case ( self % id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix ) flags = '-nofor-main' case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = '/nofor-main' case ( id_pgi , id_nvhpc ) flags = '-Mnomain' end select case ( \"c++\" , \"cpp\" , \"cxx\" ) select case ( self % id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix ) flags = '-nofor-main' case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = '/nofor-main' case ( id_pgi , id_nvhpc ) flags = '-Mnomain' end select case default error stop \"Unknown language '\" // language // '\", try \"fortran\", \"c\", \"c++\"' end select end subroutine get_main_flags","tags":"","loc":"proc/get_main_flags.html"},{"title":"get_release_compile_flags – Fortran-lang/fpm","text":"public subroutine get_release_compile_flags(id, flags) Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(out), allocatable :: flags Source Code subroutine get_release_compile_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( out ) :: flags select case ( id ) case default flags = \"\" case ( id_caf ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit case ( id_gcc ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_coarray case ( id_f95 ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit case ( id_nvhpc ) flags = & flag_pgi_backslash case ( id_ibmxl ) flags = & flag_ibmxl_backslash case ( id_intel_classic_nix ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_classic_mac ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_classic_windows ) flags = & flag_intel_opt_win // & flag_intel_fp_win // & flag_intel_align_win // & flag_intel_limit_win // & flag_intel_pthread_win // & flag_intel_nogen_win // & flag_intel_byterecl_win case ( id_intel_llvm_nix ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_llvm_windows ) flags = & flag_intel_opt_win // & flag_intel_fp_win // & flag_intel_align_win // & flag_intel_limit_win // & flag_intel_pthread_win // & flag_intel_nogen_win // & flag_intel_byterecl_win case ( id_nag ) flags = & flag_nag_opt // & flag_nag_coarray // & flag_nag_pic case ( id_lfortran ) flags = & flag_lfortran_opt end select end subroutine get_release_compile_flags","tags":"","loc":"proc/get_release_compile_flags.html"},{"title":"link – Fortran-lang/fpm","text":"public subroutine link(self, output, args, log_file, stat) Link an executable Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Source Code subroutine link ( self , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % fc // \" \" // args // \" -o \" // output , echo = self % echo , & & verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine link","tags":"","loc":"proc/link.html"},{"title":"load_from_toml – Fortran-lang/fpm","text":"public subroutine load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Type Bound archiver_t Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( archiver_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"ar\" , self % ar ) call get_value ( table , \"use-response-file\" , self % use_response_file , error , 'archiver_t' ) if ( allocated ( error )) return call get_value ( table , \"echo\" , self % echo , error , 'archiver_t' ) if ( allocated ( error )) return call get_value ( table , \"verbose\" , self % verbose , error , 'archiver_t' ) if ( allocated ( error )) return end subroutine load_from_toml","tags":"","loc":"proc/load_from_toml~8.html"},{"title":"make_archive – Fortran-lang/fpm","text":"public subroutine make_archive(self, output, args, log_file, stat) Create an archive Todo For Windows OS, use the local delete_file_win32 in stead of delete_file .\nThis may be related to a bug in Mingw64-openmp and is expected to be resolved in the future,\nsee issue #707, #708 and #808. Type Bound archiver_t Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: self Instance of the archiver object character(len=*), intent(in) :: output Name of the archive to generate type( string_t ), intent(in) :: args (:) Object files to include into the archive character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Subroutines subroutine delete_file_win32 (file) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file Source Code subroutine make_archive ( self , output , args , log_file , stat ) !> Instance of the archiver object class ( archiver_t ), intent ( in ) :: self !> Name of the archive to generate character ( len =* ), intent ( in ) :: output !> Object files to include into the archive type ( string_t ), intent ( in ) :: args (:) !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat if ( self % use_response_file ) then call write_response_file ( output // \".resp\" , args ) call run ( self % ar // output // \" @\" // output // \".resp\" , echo = self % echo , & & verbose = self % verbose , redirect = log_file , exitstat = stat ) call delete_file_win32 ( output // \".resp\" ) else call run ( self % ar // output // \" \" // string_cat ( args , \" \" ), & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end if contains subroutine delete_file_win32 ( file ) character ( len =* ), intent ( in ) :: file logical :: exist integer :: unit , iostat inquire ( file = file , exist = exist ) if ( exist ) then open ( file = file , newunit = unit ) close ( unit , status = 'delete' , iostat = iostat ) end if end subroutine delete_file_win32 end subroutine make_archive","tags":"","loc":"proc/make_archive.html"},{"title":"new_archiver – Fortran-lang/fpm","text":"public subroutine new_archiver(self, ar, echo, verbose) Create new archiver instance Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(out) :: self New instance of the archiver character(len=*), intent(in) :: ar User provided archiver command logical, intent(in) :: echo Echo compiler command logical, intent(in) :: verbose Verbose mode: dump compiler output Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: arflags = \" -rs \" integer, public :: estat character(len=*), public, parameter :: libflags = \" /OUT:\" integer, public :: os_type Source Code subroutine new_archiver ( self , ar , echo , verbose ) !> New instance of the archiver type ( archiver_t ), intent ( out ) :: self !> User provided archiver command character ( len =* ), intent ( in ) :: ar !> Echo compiler command logical , intent ( in ) :: echo !> Verbose mode: dump compiler output logical , intent ( in ) :: verbose integer :: estat , os_type character ( len =* ), parameter :: arflags = \" -rs \" , libflags = \" /OUT:\" if ( len_trim ( ar ) > 0 ) then ! Check first for ar-like commands if ( check_compiler ( ar , \"ar\" )) then self % ar = ar // arflags end if ! Check for lib-like commands if ( check_compiler ( ar , \"lib\" )) then self % ar = ar // libflags end if ! Fallback and assume ar-like behaviour self % ar = ar // arflags else os_type = get_os_type () if ( os_type /= OS_WINDOWS . and . os_type /= OS_UNKNOWN ) then self % ar = \"ar\" // arflags else ! Attempt \"ar\" call execute_command_line ( \"ar --version > \" // get_temp_filename () // \" 2>&1\" , & & exitstat = estat ) if ( estat == 0 ) then self % ar = \"ar\" // arflags else ! Then \"gcc-ar\" call execute_command_line ( \"gcc-ar --version > \" // get_temp_filename () // \" 2>&1\" , & & exitstat = estat ) if ( estat /= 0 ) then self % ar = \"lib\" // libflags else self % ar = \"gcc-ar\" // arflags end if endif end if end if self % use_response_file = os_type == OS_WINDOWS self % echo = echo self % verbose = verbose end subroutine new_archiver","tags":"","loc":"proc/new_archiver.html"},{"title":"new_compiler – Fortran-lang/fpm","text":"public subroutine new_compiler(self, fc, cc, cxx, echo, verbose) Create new compiler instance Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(out) :: self New instance of the compiler character(len=*), intent(in) :: fc Fortran compiler name or path character(len=*), intent(in) :: cc C compiler name or path character(len=*), intent(in) :: cxx C++ Compiler name or path logical, intent(in) :: echo Echo compiler command logical, intent(in) :: verbose Verbose mode: dump compiler output Source Code subroutine new_compiler ( self , fc , cc , cxx , echo , verbose ) !> New instance of the compiler type ( compiler_t ), intent ( out ) :: self !> Fortran compiler name or path character ( len =* ), intent ( in ) :: fc !> C compiler name or path character ( len =* ), intent ( in ) :: cc !> C++ Compiler name or path character ( len =* ), intent ( in ) :: cxx !> Echo compiler command logical , intent ( in ) :: echo !> Verbose mode: dump compiler output logical , intent ( in ) :: verbose self % id = get_compiler_id ( fc ) self % echo = echo self % verbose = verbose self % fc = fc if ( len_trim ( cc ) > 0 ) then self % cc = cc else call get_default_c_compiler ( self % fc , self % cc ) end if if ( len_trim ( cxx ) > 0 ) then self % cxx = cxx else call get_default_cxx_compiler ( self % fc , self % cxx ) end if end subroutine new_compiler","tags":"","loc":"proc/new_compiler.html"},{"title":"set_cpp_preprocessor_flags – Fortran-lang/fpm","text":"public pure subroutine set_cpp_preprocessor_flags(id, flags) Modify the flag_cpp_preprocessor on the basis of the compiler. Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(inout), allocatable :: flags Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: flag_cpp_preprocessor Source Code pure subroutine set_cpp_preprocessor_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( inout ) :: flags character ( len = :), allocatable :: flag_cpp_preprocessor !> Modify the flag_cpp_preprocessor on the basis of the compiler. select case ( id ) case default flag_cpp_preprocessor = \"\" case ( id_caf , id_gcc , id_f95 , id_nvhpc ) flag_cpp_preprocessor = \"-cpp\" case ( id_intel_classic_windows , id_intel_llvm_windows ) flag_cpp_preprocessor = \"/fpp\" case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , id_nag ) flag_cpp_preprocessor = \"-fpp\" case ( id_lfortran ) flag_cpp_preprocessor = \"--cpp\" end select flags = flag_cpp_preprocessor // flags end subroutine set_cpp_preprocessor_flags","tags":"","loc":"proc/set_cpp_preprocessor_flags.html"},{"title":"write_response_file – Fortran-lang/fpm","text":"public subroutine write_response_file(name, argv) Response files allow to read command line options from files.\nWhitespace is used to separate the arguments, we will use newlines\nas separator to create readable response files which can be inspected\nin case of errors. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name type( string_t ), intent(in) :: argv (:) Variables Type Visibility Attributes Name Initial integer, public :: iarg integer, public :: io Source Code subroutine write_response_file ( name , argv ) character ( len =* ), intent ( in ) :: name type ( string_t ), intent ( in ) :: argv (:) integer :: iarg , io open ( file = name , newunit = io , status = 'replace' ) do iarg = 1 , size ( argv ) write ( io , '(a)' ) unix_path ( argv ( iarg )% s ) end do close ( io ) end subroutine write_response_file","tags":"","loc":"proc/write_response_file.html"},{"title":"debug – Fortran-lang/fpm","text":"public interface debug Create debug printout Module Procedures public pure function debug_compiler (self) result(repr) String representation of a compiler object Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string public pure function debug_archiver (self) result(repr) String representation of an archiver object Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(in) :: self Instance of the archiver object Return Value character(len=:), allocatable Representation as string","tags":"","loc":"interface/debug.html"},{"title":"get_fpm_env – Fortran-lang/fpm","text":"public function get_fpm_env(env, default) result(val) Get an environment variable for fpm, this routine ensures that every variable\nused by fpm is prefixed with FPM_. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: env character(len=*), intent(in) :: default Return Value character(len=:), allocatable Source Code function get_fpm_env ( env , default ) result ( val ) character ( len =* ), intent ( in ) :: env character ( len =* ), intent ( in ) :: default character ( len = :), allocatable :: val character ( len =* ), parameter :: fpm_prefix = \"FPM_\" val = get_env ( fpm_prefix // env , default ) end function get_fpm_env","tags":"","loc":"proc/get_fpm_env.html"},{"title":"get_command_line_settings – Fortran-lang/fpm","text":"public subroutine get_command_line_settings(cmd_settings) ! canon_path is not converting “.”, etc.\n& ‘ unknown help topic “’//trim(unnamed(i)).’not found in:’,manual] Arguments Type Intent Optional Attributes Name class( fpm_cmd_settings ), intent(out), allocatable :: cmd_settings Source Code subroutine get_command_line_settings ( cmd_settings ) class ( fpm_cmd_settings ), allocatable , intent ( out ) :: cmd_settings integer , parameter :: widest = 256 character ( len = 4096 ) :: cmdarg integer :: i integer :: os type ( fpm_install_settings ), allocatable :: install_settings type ( fpm_publish_settings ), allocatable :: publish_settings type ( fpm_export_settings ) , allocatable :: export_settings type ( version_t ) :: version character ( len = :), allocatable :: common_args , compiler_args , run_args , working_dir , & & c_compiler , cxx_compiler , archiver , version_s , token_s character ( len =* ), parameter :: fc_env = \"FC\" , cc_env = \"CC\" , ar_env = \"AR\" , & & fflags_env = \"FFLAGS\" , cflags_env = \"CFLAGS\" , cxxflags_env = \"CXXFLAGS\" , ldflags_env = \"LDFLAGS\" , & & fc_default = \"gfortran\" , cc_default = \" \" , ar_default = \" \" , flags_default = \" \" , & & cxx_env = \"CXX\" , cxx_default = \" \" type ( error_t ), allocatable :: error call set_help () os = get_os_type () ! text for --version switch, select case ( os ) case ( OS_LINUX ); os_type = \"OS Type: Linux\" case ( OS_MACOS ); os_type = \"OS Type: macOS\" case ( OS_WINDOWS ); os_type = \"OS Type: Windows\" case ( OS_CYGWIN ); os_type = \"OS Type: Cygwin\" case ( OS_SOLARIS ); os_type = \"OS Type: Solaris\" case ( OS_FREEBSD ); os_type = \"OS Type: FreeBSD\" case ( OS_OPENBSD ); os_type = \"OS Type: OpenBSD\" case ( OS_UNKNOWN ); os_type = \"OS Type: Unknown\" case default ; os_type = \"OS Type: UNKNOWN\" end select ! Get current release version version = fpm_version () version_s = version % s () version_text = [ character ( len = 80 ) :: & & 'Version: ' // trim ( version_s ) // ', alpha' , & & 'Program: fpm(1)' , & & 'Description: A Fortran package manager and build system' , & & 'Home Page: https://github.com/fortran-lang/fpm' , & & 'License: MIT' , & & os_type ] ! find the subcommand name by looking for first word on command ! not starting with dash CLI_RESPONSE_FILE = . true . cmdarg = get_subcommand () common_args = & ' --directory:C \" \"' // & ' --verbose F' run_args = & ' --target \" \"' // & ' --list F' // & ' --runner \" \"' // & ' --runner-args \" \"' compiler_args = & ' --profile \" \"' // & ' --no-prune F' // & ' --compiler \"' // get_fpm_env ( fc_env , fc_default ) // '\"' // & ' --c-compiler \"' // get_fpm_env ( cc_env , cc_default ) // '\"' // & ' --cxx-compiler \"' // get_fpm_env ( cxx_env , cxx_default ) // '\"' // & ' --archiver \"' // get_fpm_env ( ar_env , ar_default ) // '\"' // & ' --flag:: \"' // get_fpm_env ( fflags_env , flags_default ) // '\"' // & ' --c-flag:: \"' // get_fpm_env ( cflags_env , flags_default ) // '\"' // & ' --cxx-flag:: \"' // get_fpm_env ( cxxflags_env , flags_default ) // '\"' // & ' --link-flag:: \"' // get_fpm_env ( ldflags_env , flags_default ) // '\"' ! now set subcommand-specific help text and process commandline ! arguments. Then call subcommand routine select case ( trim ( cmdarg )) case ( 'run' ) call set_args ( common_args // compiler_args // run_args // '& & --all F & & --example F& & --' , help_run , version_text ) call check_build_vals () if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif if ( specified ( 'target' ) ) then call split ( sget ( 'target' ), tnames , delimiters = ' ,:' ) names = [ character ( len = max ( len ( names ), len ( tnames ))) :: names , tnames ] endif ! convert --all to '*' if ( lget ( 'all' )) then names = [ character ( len = max ( len ( names ), 1 )) :: names , '*' ] endif ! convert special string '..' to equivalent (shorter) '*' ! to allow for a string that does not require shift-key and quoting do i = 1 , size ( names ) if ( names ( i ) == '..' ) names ( i ) = '*' enddo ! If there are additional command-line arguments, remove the additional ! double quotes which have been added by M_CLI2 val_runner_args = sget ( 'runner-args' ) call remove_characters_in_set ( val_runner_args , set = '\"' ) c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( fpm_run_settings :: cmd_settings ) val_runner = sget ( 'runner' ) if ( specified ( 'runner' ) . and . val_runner == '' ) val_runner = 'echo' cmd_settings = fpm_run_settings (& & args = remaining ,& & profile = val_profile ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & example = lget ( 'example' ), & & list = lget ( 'list' ),& & build_tests = . false .,& & name = names ,& & runner = val_runner ,& & runner_args = val_runner_args , & & verbose = lget ( 'verbose' ) ) case ( 'build' ) call set_args ( common_args // compiler_args // '& & --list F & & --show-model F & & --dump \" \" & & --tests F & & --' , help_build , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) val_dump = sget ( 'dump' ) if ( specified ( 'dump' ) . and . val_dump == '' ) val_dump = 'fpm_model.toml' allocate ( fpm_build_settings :: cmd_settings ) cmd_settings = fpm_build_settings ( & & profile = val_profile ,& & dump = val_dump ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & list = lget ( 'list' ),& & show_model = lget ( 'show-model' ),& & build_tests = lget ( 'tests' ),& & verbose = lget ( 'verbose' ) ) case ( 'new' ) call set_args ( common_args // '& & --src F & & --lib F & & --app F & & --test F & & --example F & & --backfill F & & --full F & & --bare F' , & & help_new , version_text ) select case ( size ( unnamed )) case ( 1 ) if ( lget ( 'backfill' )) then name = '.' else write ( stderr , '(*(7x,g0,/))' ) & & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]|[--full|--bare] [--backfill]' call fpm_stop ( 1 , 'directory name required' ) endif case ( 2 ) name = trim ( unnamed ( 2 )) case default write ( stderr , '(7x,g0)' ) & & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]| [--full|--bare] [--backfill]' call fpm_stop ( 2 , 'only one directory name allowed' ) end select !*! canon_path is not converting \".\", etc. if ( name == '.' ) then call get_current_directory ( name , error ) if ( allocated ( error )) then write ( stderr , '(\"[Error]\", 1x, a)' ) error % message stop 1 endif endif name = canon_path ( name ) if ( . not . is_fortran_name ( to_fortran_name ( basename ( name ))) ) then write ( stderr , '(g0)' ) [ character ( len = 72 ) :: & & ' the fpm project name must be made of up to 63 ASCII letters,' , & & ' numbers, underscores, or hyphens, and start with a letter.' ] call fpm_stop ( 4 , ' ' ) endif allocate ( fpm_new_settings :: cmd_settings ) if ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' , 'bare' ])) & & . and . lget ( 'full' ) ) then write ( stderr , '(*(a))' )& & ' --full and any of [--src|--lib,--app,--test,--example,--bare]' , & & ' are mutually exclusive.' call fpm_stop ( 5 , ' ' ) elseif ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' , 'full' ])) & & . and . lget ( 'bare' ) ) then write ( stderr , '(*(a))' )& & ' --bare and any of [--src|--lib,--app,--test,--example,--full]' , & & ' are mutually exclusive.' call fpm_stop ( 3 , ' ' ) elseif ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' ]) ) ) then cmd_settings = fpm_new_settings (& & backfill = lget ( 'backfill' ), & & name = name , & & with_executable = lget ( 'app' ), & & with_lib = any ([ lget ( 'lib' ), lget ( 'src' )]), & & with_test = lget ( 'test' ), & & with_example = lget ( 'example' ), & & verbose = lget ( 'verbose' ) ) else ! default if no specific directories are requested cmd_settings = fpm_new_settings (& & backfill = lget ( 'backfill' ) , & & name = name , & & with_executable = . true ., & & with_lib = . true ., & & with_test = . true ., & & with_example = lget ( 'full' ), & & with_full = lget ( 'full' ), & & with_bare = lget ( 'bare' ), & & verbose = lget ( 'verbose' ) ) endif case ( 'help' , 'manual' ) call set_args ( common_args , help_help , version_text ) if ( size ( unnamed ) < 2 ) then if ( unnamed ( 1 ) == 'help' ) then unnamed = [ ' ' , 'fpm' ] else unnamed = manual endif elseif ( unnamed ( 2 ) == 'manual' ) then unnamed = manual endif allocate ( character ( len = widest ) :: help_text ( 0 )) do i = 2 , size ( unnamed ) select case ( unnamed ( i )) case ( ' ' ) case ( 'fpm ' ) help_text = [ character ( len = widest ) :: help_text , help_fpm ] case ( 'new ' ) help_text = [ character ( len = widest ) :: help_text , help_new ] case ( 'build ' ) help_text = [ character ( len = widest ) :: help_text , help_build ] case ( 'install' ) help_text = [ character ( len = widest ) :: help_text , help_install ] case ( 'run ' ) help_text = [ character ( len = widest ) :: help_text , help_run ] case ( 'test ' ) help_text = [ character ( len = widest ) :: help_text , help_test ] case ( 'runner' ) help_text = [ character ( len = widest ) :: help_text , help_runner ] case ( 'list ' ) help_text = [ character ( len = widest ) :: help_text , help_list ] case ( 'update ' ) help_text = [ character ( len = widest ) :: help_text , help_update ] case ( 'help ' ) help_text = [ character ( len = widest ) :: help_text , help_help ] case ( 'version' ) help_text = [ character ( len = widest ) :: help_text , version_text ] case ( 'clean' ) help_text = [ character ( len = widest ) :: help_text , help_clean ] case ( 'publish' ) help_text = [ character ( len = widest ) :: help_text , help_publish ] case default help_text = [ character ( len = widest ) :: help_text , & & ' unknown help topic \"' // trim ( unnamed ( i )) // '\"' ] !!& ' unknown help topic \"'//trim(unnamed(i)).'not found in:',manual] end select enddo call printhelp ( help_text ) case ( 'install' ) call set_args ( common_args // compiler_args // '& & --no-rebuild F --prefix \" \" & & --list F & & --libdir \"lib\" --bindir \"bin\" --includedir \"include\"' , & help_install , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( install_settings , source = fpm_install_settings (& list = lget ( 'list' ), & profile = val_profile ,& prune = . not . lget ( 'no-prune' ), & compiler = val_compiler , & c_compiler = c_compiler , & cxx_compiler = cxx_compiler , & archiver = archiver , & flag = val_flag , & cflag = val_cflag , & cxxflag = val_cxxflag , & ldflag = val_ldflag , & no_rebuild = lget ( 'no-rebuild' ), & verbose = lget ( 'verbose' ))) call get_char_arg ( install_settings % prefix , 'prefix' ) call get_char_arg ( install_settings % libdir , 'libdir' ) call get_char_arg ( install_settings % bindir , 'bindir' ) call get_char_arg ( install_settings % includedir , 'includedir' ) call move_alloc ( install_settings , cmd_settings ) case ( 'list' ) call set_args ( common_args // '& & --list F& &' , help_list , version_text ) if ( lget ( 'list' )) then help_text = [ character ( widest ) :: help_list_nodash , help_list_dash ] else help_text = help_list_nodash endif call printhelp ( help_text ) case ( 'test' ) call set_args ( common_args // compiler_args // run_args // ' --' , & help_test , version_text ) call check_build_vals () if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif if ( specified ( 'target' ) ) then call split ( sget ( 'target' ), tnames , delimiters = ' ,:' ) names = [ character ( len = max ( len ( names ), len ( tnames ))) :: names , tnames ] endif ! convert special string '..' to equivalent (shorter) '*' ! to allow for a string that does not require shift-key and quoting do i = 1 , size ( names ) if ( names ( i ) == '..' ) names ( i ) = '*' enddo ! If there are additional command-line arguments, remove the additional ! double quotes which have been added by M_CLI2 val_runner_args = sget ( 'runner-args' ) call remove_characters_in_set ( val_runner_args , set = '\"' ) c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( fpm_test_settings :: cmd_settings ) val_runner = sget ( 'runner' ) if ( specified ( 'runner' ) . and . val_runner == '' ) val_runner = 'echo' cmd_settings = fpm_test_settings (& & args = remaining , & & profile = val_profile , & & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & example = . false ., & & list = lget ( 'list' ), & & build_tests = . true ., & & name = names , & & runner = val_runner , & & runner_args = val_runner_args , & & verbose = lget ( 'verbose' )) case ( 'update' ) call set_args ( common_args // ' --fetch-only F --clean F --dump \" \" ' , & help_update , version_text ) if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif val_dump = sget ( 'dump' ) if ( specified ( 'dump' ) . and . val_dump == '' ) val_dump = 'fpm_dependencies.toml' allocate ( fpm_update_settings :: cmd_settings ) cmd_settings = fpm_update_settings ( name = names , dump = val_dump , & fetch_only = lget ( 'fetch-only' ), verbose = lget ( 'verbose' ), & clean = lget ( 'clean' )) case ( 'export' ) call set_args ( common_args // compiler_args // '& & --manifest \"filename\" & & --model \"filename\" & & --dependencies \"filename\" ' , & help_build , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( export_settings , source = fpm_export_settings (& profile = val_profile ,& prune = . not . lget ( 'no-prune' ), & compiler = val_compiler , & c_compiler = c_compiler , & cxx_compiler = cxx_compiler , & archiver = archiver , & flag = val_flag , & cflag = val_cflag , & show_model = . true ., & cxxflag = val_cxxflag , & ldflag = val_ldflag , & verbose = lget ( 'verbose' ))) call get_char_arg ( export_settings % dump_model , 'model' ) call get_char_arg ( export_settings % dump_manifest , 'manifest' ) call get_char_arg ( export_settings % dump_dependencies , 'dependencies' ) call move_alloc ( export_settings , cmd_settings ) case ( 'clean' ) call set_args ( common_args // & & ' --registry-cache' // & & ' --skip' // & & ' --all' , & help_clean , version_text ) block logical :: skip , clean_all skip = lget ( 'skip' ) clean_all = lget ( 'all' ) if ( all ([ skip , clean_all ])) then call fpm_stop ( 6 , 'Do not specify both --skip and --all options on the clean subcommand.' ) end if allocate ( fpm_clean_settings :: cmd_settings ) cmd_settings = fpm_clean_settings ( & & registry_cache = lget ( 'registry-cache' ), & & clean_skip = skip , & & clean_all = clean_all ) end block case ( 'publish' ) call set_args ( common_args // compiler_args // '& & --show-package-version F & & --show-upload-data F & & --dry-run F & & --token \" \" & & --list F & & --show-model F & & --tests F & & --' , help_publish , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) token_s = sget ( 'token' ) allocate ( fpm_publish_settings :: cmd_settings ) cmd_settings = fpm_publish_settings ( & & show_package_version = lget ( 'show-package-version' ), & & show_upload_data = lget ( 'show-upload-data' ), & & is_dry_run = lget ( 'dry-run' ), & & profile = val_profile ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & list = lget ( 'list' ),& & show_model = lget ( 'show-model' ),& & build_tests = lget ( 'tests' ),& & verbose = lget ( 'verbose' ),& & token = token_s ) case default if ( cmdarg . ne . '' . and . which ( 'fpm-' // cmdarg ). ne . '' ) then call run ( 'fpm-' // trim ( cmdarg ) // ' ' // get_command_arguments_quoted (),. false .) stop else call set_args ( '& & --list F& &' , help_fpm , version_text ) ! Note: will not get here if --version or --usage or --help ! is present on commandline if ( lget ( 'list' )) then help_text = help_list_dash elseif ( len_trim ( cmdarg ) == 0 ) then write ( stdout , '(*(a))' ) 'Fortran Package Manager:' write ( stdout , '(*(a))' ) ' ' help_text = [ character ( widest ) :: help_list_nodash , help_usage ] else write ( stderr , '(*(a))' ) ' unknown subcommand [' , & & trim ( cmdarg ), ']' help_text = [ character ( widest ) :: help_list_dash , help_usage ] endif call printhelp ( help_text ) endif end select if ( allocated ( cmd_settings )) then working_dir = sget ( \"directory\" ) call move_alloc ( working_dir , cmd_settings % working_dir ) end if contains subroutine check_build_vals () val_compiler = sget ( 'compiler' ) if ( val_compiler == '' ) val_compiler = 'gfortran' val_flag = \" \" // sget ( 'flag' ) val_cflag = \" \" // sget ( 'c-flag' ) val_cxxflag = \" \" // sget ( 'cxx-flag' ) val_ldflag = \" \" // sget ( 'link-flag' ) val_profile = sget ( 'profile' ) end subroutine check_build_vals !> Print help text and stop subroutine printhelp ( lines ) character ( len = :), intent ( in ), allocatable :: lines (:) integer :: iii , ii if ( allocated ( lines )) then ii = size ( lines ) if ( ii > 0 . and . len ( lines ) > 0 ) then write ( stdout , '(g0)' )( trim ( lines ( iii )), iii = 1 , ii ) else write ( stdout , '(a)' ) ' *printhelp* output requested is empty' endif endif stop end subroutine printhelp end subroutine get_command_line_settings","tags":"","loc":"proc/get_command_line_settings.html"},{"title":"cmd_new – Fortran-lang/fpm","text":"public subroutine cmd_new(settings) TOP DIRECTORY NAME PROCESSING\nsee if requested new directory already exists and process appropriately\ntemporarily change to new directory as a test. NB: System dependent Arguments Type Intent Optional Attributes Name type( fpm_new_settings ), intent(in) :: settings Source Code subroutine cmd_new ( settings ) type ( fpm_new_settings ), intent ( in ) :: settings integer , parameter :: tfc = selected_char_kind ( 'DEFAULT' ) character ( len = :, kind = tfc ), allocatable :: bname ! baeename of NAME character ( len = :, kind = tfc ), allocatable :: tomlfile (:) character ( len = :, kind = tfc ), allocatable :: littlefile (:) !> TOP DIRECTORY NAME PROCESSING !> see if requested new directory already exists and process appropriately if ( exists ( settings % name ) . and . . not . settings % backfill ) then write ( stderr , '(*(g0,1x))' )& & '' , settings % name , 'already exists.' write ( stderr , '(*(g0,1x))' )& & ' perhaps you wanted to add --backfill ?' return elseif ( is_dir ( settings % name ) . and . settings % backfill ) then write ( * , '(*(g0))' ) 'backfilling ' , settings % name elseif ( exists ( settings % name ) ) then write ( stderr , '(*(g0,1x))' )& & '' , settings % name , 'already exists and is not a directory.' return else ! make new directory call mkdir ( settings % name ) endif !> temporarily change to new directory as a test. NB: System dependent call run ( 'cd ' // settings % name ) ! NOTE: need some system routines to handle filenames like \".\" ! like realpath() or getcwd(). bname = basename ( settings % name ) littlefile = [ character ( len = 80 ) :: '# ' // bname , 'My cool new project!' ] ! create NAME/README.md call warnwrite ( join_path ( settings % name , 'README.md' ), littlefile ) ! start building NAME/fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: & & ' # This is your fpm(Fortran Package Manager) manifest file ' ,& & ' # (\"fpm.toml\"). It is heavily annotated to help guide you though ' ,& & ' # customizing a package build, although the defaults are sufficient ' ,& & ' # for many basic packages. ' ,& & ' # ' ,& & ' # The manifest file is not only used to provide metadata identifying ' ,& & ' # your project (so it can be used by others as a dependency). It can ' ,& & ' # specify where your library and program sources live, what the name ' ,& & ' # of the executable(s) will be, what files to build, dependencies on ' ,& & ' # other fpm packages, and what external libraries are required. ' ,& & ' # ' ,& & ' # The manifest format must conform to the TOML configuration file ' ,& & ' # standard. ' ,& & ' # ' ,& & ' # TOML files support flexible use of white-space and commenting of the ' ,& & ' # configuration data, but for clarity in this sample active directives ' ,& & ' # begin in column one. Inactive example directives are commented ' ,& & ' # out with a pound character (\"#\") but begin in column one as well. ' ,& & ' # Commentary begins with a pound character in column three. ' ,& & ' # ' ,& & ' # This file draws heavily upon the following references: ' ,& & ' # ' ,& & ' # The fpm home page at ' ,& & ' # https://github.com/fortran-lang/fpm ' ,& & ' # A complete list of keys and their attributes at ' ,& & ' # https://github.com/fortran-lang/fpm/blob/main/manifest-reference.md ' ,& & ' # examples of fpm project packaging at ' ,& & ' # https://github.com/fortran-lang/fpm/blob/main/PACKAGING.md ' ,& & ' # The Fortran TOML file interface and it''s references at ' ,& & ' # https://github.com/toml-f/toml-f ' ,& & ' # ' ,& & ' #----------------------- ' ,& & ' # project Identification ' ,& & ' #----------------------- ' ,& & ' # We begin with project metadata at the manifest root. This data is designed ' ,& & ' # to aid others when searching for the project in a repository and to ' ,& & ' # identify how and when to contact the package supporters. ' ,& & ' ' ,& & 'name = \"' // bname // '\"' ,& & ' # The project name (required) is how the project will be referred to. ' ,& & ' # The name is used by other packages using it as a dependency. It also ' ,& & ' # is used as the default name of any library built and the optional ' ,& & ' # default executable built from app/main.f90. It must conform to the rules ' ,& & ' # for a Fortran variable name. ' ,& & ' ' ,& & 'version = \"0.1.0\" ' ,& & ' # The project version number is a string. A recommended scheme for ' ,& & ' # specifying versions is the Semantic Versioning scheme. ' ,& & ' ' ,& & 'license = \"license\" ' ,& & ' # Licensing information specified using SPDX identifiers is preferred ' ,& & ' # (eg. \"Apache-2.0 OR MIT\" or \"LGPL-3.0-or-later\"). ' ,& & ' ' ,& & 'maintainer = \"jane.doe@example.com\" ' ,& & ' # Information on the project maintainer and means to reach out to them. ' ,& & ' ' ,& & 'author = \"Jane Doe\" ' ,& & ' # Information on the project author. ' ,& & ' ' ,& & 'copyright = \"Copyright 2020 Jane Doe\" ' ,& & ' # A statement clarifying the Copyright status of the project. ' ,& & ' ' ,& & '#description = \"A short project summary in plain text\" ' ,& & ' # The description provides a short summary on the project. It should be ' ,& & ' # plain text and not use any markup formatting. ' ,& & ' ' ,& & '#categories = [\"fortran\", \"graphics\"] ' ,& & ' # Categories associated with the project. Listing only one is preferred. ' ,& & ' ' ,& & '#keywords = [\"hdf5\", \"mpi\"] ' ,& & ' # The keywords field is an array of strings describing the project. ' ,& & ' ' ,& & '#homepage = \"https://stdlib.fortran-lang.org\" ' ,& & ' # URL to the webpage of the project. ' ,& & ' ' ,& & ' # ----------------------------------------- ' ,& & ' # We are done with identifying the project. ' ,& & ' # ----------------------------------------- ' ,& & ' # ' ,& & ' # Now lets start describing how the project should be built. ' ,& & ' # ' ,& & ' # Note tables would go here but we will not be talking about them (much)!!' ,& & ' # ' ,& & ' # Tables are a way to explicitly specify large numbers of programs in ' ,& & ' # a compact format instead of individual per-program entries in the ' ,& & ' # [[executable]], [[test]], and [[example]] sections to follow but ' ,& & ' # will not be discussed further except for the following notes: ' ,& & ' # ' ,& & ' # + Tables must appear (here) before any sections are declared. Once a ' ,& & ' # section is specified in a TOML file everything afterwards must be ' ,& & ' # values for that section or the beginning of a new section. A simple ' ,& & ' # example looks like: ' ,& & ' ' ,& & '#executable = [ ' ,& & '# { name = \"a-prog\" }, ' ,& & '# { name = \"app-tool\", source-dir = \"tool\" }, ' ,& & '# { name = \"fpm-man\", source-dir = \"tool\", main=\"fman.f90\" } ' ,& & '#] ' ,& & ' ' ,& & ' # This would be in lieue of the [[executable]] section found later in this ' ,& & ' # configuration file. ' ,& & ' # + See the reference documents (at the beginning of this document) ' ,& & ' # for more information on tables if you have long lists of programs ' ,& & ' # to build and are not simply depending on auto-detection. ' ,& & ' # ' ,& & ' # Now lets begin the TOML sections (lines beginning with \"[\") ... ' ,& & ' # ' ,& & ' ' ,& & '[install] # Options for the \"install\" subcommand ' ,& & ' ' ,& & ' # When you run the \"install\" subcommand only executables are installed by ' ,& & ' # default on the local system. Library projects that will be used outside of ' ,& & ' # \"fpm\" can set the \"library\" boolean to also allow installing the module ' ,& & ' # files and library archive. Without this being set to \"true\" an \"install\" ' ,& & ' # subcommand ignores parameters that specify library installation. ' ,& & ' ' ,& & 'library = false ' ,& & ' ' ,& & '[build] # General Build Options ' ,& & ' ' ,& & ' ### Automatic target discovery ' ,& & ' # ' ,& & ' # Normally fpm recursively searches the app/, example/, and test/ directories ' ,& & ' # for program sources and builds them. To disable this automatic discovery of ' ,& & ' # program targets set the following to \"false\": ' ,& & ' ' ,& & '#auto-executables = true ' ,& & '#auto-examples = true ' ,& & '#auto-tests = true ' ,& & ' ' ,& & ' ### Package-level External Library Links ' ,& & ' # ' ,& & ' # To declare link-time dependencies on external libraries a list of ' ,& & ' # native libraries can be specified with the \"link\" entry. You may ' ,& & ' # have one library name or a list of strings in case several ' ,& & ' # libraries should be linked. This list of library dependencies is ' ,& & ' # exported to dependent packages. You may have to alter your library ' ,& & ' # search-path to ensure the libraries can be accessed. Typically, ' ,& & ' # this is done with the LD_LIBRARY_PATH environment variable on ULS ' ,& & ' # (Unix-Like Systems). You only specify the core name of the library ' ,& & ' # (as is typical with most programming environments, where you ' ,& & ' # would specify \"-lz\" on your load command to link against the zlib ' ,& & ' # compression library even though the library file would typically be ' ,& & ' # a file called \"libz.a\" \"or libz.so\"). So to link against that library ' ,& & ' # you would specify: ' ,& & ' ' ,& & '#link = \"z\" ' ,& & ' ' ,& & ' # Note that in some cases the order of the libraries matters: ' ,& & ' ' ,& & '#link = [\"blas\", \"lapack\"] ' ,& & '' ] endif if ( settings % with_bare ) then elseif ( settings % with_lib ) then call mkdir ( join_path ( settings % name , 'src' ) ) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & '[library] ' ,& & ' ' ,& & ' # You can change the name of the directory to search for your library ' ,& & ' # source from the default of \"src/\". Library targets are exported ' ,& & ' # and usable by other projects. ' ,& & ' ' ,& & 'source-dir=\"src\" ' ,& & ' ' ,& & ' # this can be a list: ' ,& & ' ' ,& & '#source-dir=[\"src\", \"src2\"] ' ,& & ' ' ,& & ' # More complex libraries may organize their modules in subdirectories. ' ,& & ' # For modules in a top-level directory fpm requires (but does not ' ,& & ' # enforce) that: ' ,& & ' # ' ,& & ' # + The module has the same name as the source file. This is important. ' ,& & ' # + There should be only one module per file. ' ,& & ' # ' ,& & ' # These two requirements simplify the build process for fpm. As Fortran ' ,& & ' # compilers emit module files (.mod) with the same name as the module ' ,& & ' # itself (but not the source file, .f90), naming the module the same ' ,& & ' # as the source file allows fpm to: ' ,& & ' # ' ,& & ' # + Uniquely and exactly map a source file (.f90) to its object (.o) ' ,& & ' # and module (.mod) files. ' ,& & ' # + Avoid conflicts with modules of the same name that could appear ' ,& & ' # in dependency packages. ' ,& & ' # ' ,& & ' ### Multi-level library source ' ,& & ' # You can place your module source files in any number of levels of ' ,& & ' # subdirectories inside your source directory, but there are certain naming ' ,& & ' # conventions to be followed -- module names must contain the path components ' ,& & ' # of the directory that its source file is in. ' ,& & ' # ' ,& & ' # This rule applies generally to any number of nested directories and ' ,& & ' # modules. For example, src/a/b/c/d.f90 must define a module called a_b_c_d. ' ,& & ' # Again, this is not enforced but may be required in future releases. ' ,& & '' ] endif ! create placeholder module src/bname.f90 littlefile = [ character ( len = 80 ) :: & & 'module ' // to_fortran_name ( bname ), & & ' implicit none' , & & ' private' , & & '' , & & ' public :: say_hello' , & & 'contains' , & & ' subroutine say_hello' , & & ' print *, \"Hello, ' // bname // '!\"' , & & ' end subroutine say_hello' , & & 'end module ' // to_fortran_name ( bname )] ! create NAME/src/NAME.f90 call warnwrite ( join_path ( settings % name , 'src' , bname // '.f90' ),& & littlefile ) endif if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile ,& & '[dependencies] ' ,& & ' ' ,& & ' # Inevitably, you will want to be able to include other packages in ' ,& & ' # a project. Fpm makes this incredibly simple, by taking care of ' ,& & ' # fetching and compiling your dependencies for you. You just tell it ' ,& & ' # what your dependencies names are, and where to find them. ' ,& & ' # ' ,& & ' # If you are going to distribute your package only place dependencies ' ,& & ' # here someone using your package as a remote dependency needs built. ' ,& & ' # You can define dependencies just for developer executables in the ' ,& & ' # next section, or even for specific executables as we will see below ' ,& & ' # (Then fpm will still fetch and compile it when building your ' ,& & ' # developer executables, but users of your library will not have to). ' ,& & ' # ' ,& & ' ## GLOBAL DEPENDENCIES (exported with your project) ' ,& & ' # ' ,& & ' # Typically, dependencies are defined by specifying the project''s ' ,& & ' # git repository. ' ,& & ' # ' ,& & ' # You can be specific about which version of a dependency you would ' ,& & ' # like. By default the latest default branch is used. You can ' ,& & ' # optionally specify a branch, a tag or a commit value. ' ,& & ' # ' ,& & ' # So here are several alternates for specifying a remote dependency (you ' ,& & ' # can have at most one of \"branch\", \"rev\" or \"tag\" present): ' ,& & ' ' ,& & '#stdlib = { git = \"https://github.com/LKedward/stdlib-fpm.git\" } ' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\",branch = \"master\" },' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\", tag = \"v0.1.0\" }, ' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\", rev = \"5a9b7a8\" }. ' ,& & ' ' ,& & ' # There may be multiple packages listed: ' ,& & ' ' ,& & '#M_strings = { git = \"https://github.com/urbanjost/M_strings.git\" } ' ,& & '#M_time = { git = \"https://github.com/urbanjost/M_time.git\" } ' ,& & ' ' ,& & ' # ' ,& & ' # You can even specify the local path to another project if it is in ' ,& & ' # a sub-folder (If for example you have got another fpm package **in ' ,& & ' # the same repository**) like this: ' ,& & ' ' ,& & '#M_strings = { path = \"M_strings\" } ' ,& & ' ' ,& & ' # This tells fpm that we depend on a crate called M_strings which is found ' ,& & ' # in the M_strings folder (relative to the fpm.toml it’s written in). ' ,& & ' # ' ,& & ' # For a more verbose layout use normal tables rather than inline tables ' ,& & ' # to specify dependencies: ' ,& & ' ' ,& & '#[dependencies.toml-f] ' ,& & '#git = \"https://github.com/toml-f/toml-f\" ' ,& & '#rev = \"2f5eaba864ff630ba0c3791126a3f811b6e437f3\" ' ,& & ' ' ,& & ' # Now you can use any modules from these libraries anywhere in your ' ,& & ' # code -- whether is in your library source or a program source. ' ,& & ' ' ,& & '[dev-dependencies] ' ,& & ' ' ,& & ' ## Dependencies Only for Development ' ,& & ' # ' ,& & ' # You can specify dependencies your library or application does not ' ,& & ' # depend on in a similar way. The difference is that these will not ' ,& & ' # be exported as part of your project to those using it as a remote ' ,& & ' # dependency. ' ,& & ' # ' ,& & ' # Currently, like a global dependency it will still be available for ' ,& & ' # all codes. It is up to the developer to ensure that nothing except ' ,& & ' # developer test programs rely upon it. ' ,& & ' ' ,& & '#M_msg = { git = \"https://github.com/urbanjost/M_msg.git\" } ' ,& & '#M_verify = { git = \"https://github.com/urbanjost/M_verify.git\" } ' ,& & '' ] endif if ( settings % with_bare ) then elseif ( settings % with_executable ) then ! create next section of fpm.toml call mkdir ( join_path ( settings % name , 'app' )) ! create NAME/app or stop if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & ' #----------------------------------- ' ,& & ' ## Application-specific declarations ' ,& & ' #----------------------------------- ' ,& & ' # Now lets begin entries for the TOML tables (lines beginning with \"[[\") ' ,& & ' # that describe the program sources -- applications, tests, and examples. ' ,& & ' # ' ,& & ' # First we will configuration individual applications run with \"fpm run\". ' ,& & ' # ' ,& & ' # + the \"name\" entry for the executable to be built must always ' ,& & ' # be specified. The name must satisfy the rules for a Fortran ' ,& & ' # variable name. This will be the name of the binary installed by ' ,& & ' # the \"install\" subcommand and used on the \"run\" subcommand. ' ,& & ' # + The source directory for each executable can be adjusted by the ' ,& & ' # \"source-dir\" entry. ' ,& & ' # + The basename of the source file containing the program body can ' ,& & ' # be specified with the \"main\" entry. ' ,& & ' # + Executables can also specify their own external package and ' ,& & ' # library link dependencies. ' ,& & ' # ' ,& & ' # Currently, like a global dependency any external package dependency ' ,& & ' # will be available for all codes. It is up to the developer to ensure ' ,& & ' # that nothing except the application programs specified rely upon it. ' ,& & ' # ' ,& & ' # Note if your application needs to use a module internally, but you do not ' ,& & ' # intend to build it as a library to be used in other projects, you can ' ,& & ' # include the module in your program source file or directory as well. ' ,& & ' ' ,& & '[[executable]] ' ,& & 'name=\"' // bname // '\"' ,& & 'source-dir=\"app\" ' ,& & 'main=\"main.f90\" ' ,& & ' ' ,& & ' # You may repeat this pattern to define additional applications. For instance,' ,& & ' # the following sample illustrates all accepted options, where \"link\" and ' ,& & ' # \"executable.dependencies\" keys are the same as the global external library ' ,& & ' # links and package dependencies described previously except they apply ' ,& & ' # only to this executable: ' ,& & ' ' ,& & '#[[ executable ]] ' ,& & '#name = \"app-name\" ' ,& & '#source-dir = \"prog\" ' ,& & '#main = \"program.f90\" ' ,& & '#link = \"z\" ' ,& & '#[executable.dependencies] ' ,& & '#M_CLI = { git = \"https://github.com/urbanjost/M_CLI.git\" } ' ,& & '#helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } ' ,& & '#M_path = { git = \"https://github.com/urbanjost/M_path.git\" } ' ,& & '' ] endif if ( exists ( bname // '/src/' )) then littlefile = [ character ( len = 80 ) :: & & 'program main' , & & ' use ' // to_fortran_name ( bname ) // ', only: say_hello' , & & ' implicit none' , & & '' , & & ' call say_hello()' , & & 'end program main' ] else littlefile = [ character ( len = 80 ) :: & & 'program main' , & & ' implicit none' , & & '' , & & ' print *, \"hello from project ' // bname // '\"' , & & 'end program main' ] endif call warnwrite ( join_path ( settings % name , 'app/main.f90' ), littlefile ) endif if ( settings % with_bare ) then elseif ( settings % with_test ) then ! create NAME/test or stop call mkdir ( join_path ( settings % name , 'test' )) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile ,& & '[[test]] ' ,& & ' ' ,& & ' # The same declarations can be made for test programs, which are ' ,& & ' # executed with the \"fpm test\" command and are not build when your ' ,& & ' # package is used as a dependency by other packages. These are ' ,& & ' # typically unit tests of the package only used during package ' ,& & ' # development. ' ,& & ' ' ,& & 'name=\"runTests\" ' ,& & 'source-dir=\"test\" ' ,& & 'main=\"check.f90\" ' ,& & ' ' ,& & ' # you may repeat this pattern to add additional explicit test program ' ,& & ' # parameters. The following example contains a sample of all accepted ' ,& & ' # options. ' ,& & ' ' ,& & '#[[ test ]] ' ,& & '#name = \"tester\" ' ,& & '#source-dir=\"test\" ' ,& & '#main=\"tester.f90\" ' ,& & '#link = [\"blas\", \"lapack\"] ' ,& & '#[test.dependencies] ' ,& & '#M_CLI2 = { git = \"https://github.com/urbanjost/M_CLI2.git\" } ' ,& & '#M_io = { git = \"https://github.com/urbanjost/M_io.git\" } ' ,& & '#M_system= { git = \"https://github.com/urbanjost/M_system.git\" } ' ,& & '' ] endif littlefile = [ character ( len = 80 ) :: & & 'program check' , & & 'implicit none' , & & '' , & & 'print *, \"Put some tests in here!\"' , & & 'end program check' ] ! create NAME/test/check.f90 call warnwrite ( join_path ( settings % name , 'test/check.f90' ), littlefile ) endif if ( settings % with_bare ) then elseif ( settings % with_example ) then ! create NAME/example or stop call mkdir ( join_path ( settings % name , 'example' )) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & '[[example]] ' ,& & ' ' ,& & ' # Example applications for a project are defined here. ' ,& & ' # These are run via \"fpm run --example NAME\" and like the ' ,& & ' # test applications, are not built when this package is used as a ' ,& & ' # dependency by other packages. ' ,& & ' ' ,& & 'name=\"demo\" ' ,& & 'source-dir=\"example\" ' ,& & 'main=\"demo.f90\" ' ,& & ' ' ,& & ' # ' ,& & ' # you may add additional programs to the example table. The following ' ,& & ' # example contains a sample of all accepted options ' ,& & ' ' ,& & '#[[ example ]] ' ,& & '#name = \"example-tool\" ' ,& & '#source-dir=\"example\" ' ,& & '#main=\"tool.f90\" ' ,& & '#link = \"z\" ' ,& & '#[example.dependencies] ' ,& & '#M_kracken95 = { git = \"https://github.com/urbanjost/M_kracken95.git\" } ' ,& & '#datetime = {git = \"https://github.com/wavebitscientific/datetime-fortran.git\" }' ,& & '' ] endif littlefile = [ character ( len = 80 ) :: & & 'program demo' , & & 'implicit none' , & & '' , & & 'print *, \"Put some examples in here!\"' , & & 'end program demo' ] ! create NAME/example/demo.f90 call warnwrite ( join_path ( settings % name , 'example/demo.f90' ), littlefile ) endif ! now that built it write NAME/fpm.toml if ( allocated ( tomlfile ) ) then call validate_toml_data ( tomlfile ) call warnwrite ( join_path ( settings % name , 'fpm.toml' ), tomlfile ) else call create_verified_basic_manifest ( join_path ( settings % name , 'fpm.toml' )) endif ! assumes git(1) is installed and in path if ( which ( 'git' ) /= '' ) then call run ( 'git init ' // settings % name ) endif contains function git_metadata ( what ) result ( returned ) !> get metadata values such as email address and git name from git(1) or return appropriate default use fpm_filesystem , only : get_temp_filename , getline character ( len =* ), intent ( in ) :: what ! keyword designating what git metatdata to query character ( len = :), allocatable :: returned ! value to return for requested keyword character ( len = :), allocatable :: command character ( len = :), allocatable :: temp_filename character ( len = :), allocatable :: iomsg character ( len = :), allocatable :: temp_value integer :: stat , unit temp_filename = get_temp_filename () ! for known keywords set default value for RETURNED and associated git(1) command for query select case ( what ) case ( 'uname' ) returned = \"Jane Doe\" command = \"git config --get user.name > \" // temp_filename case ( 'email' ) returned = \"jane.doe@example.com\" command = \"git config --get user.email > \" // temp_filename case default write ( stderr , '(*(g0,1x))' )& & ' *git_metadata* unknown metadata name ' , trim ( what ) returned = '' return end select ! Execute command if git(1) is in command path if ( which ( 'git' ) /= '' ) then call run ( command , exitstat = stat ) if ( stat /= 0 ) then ! If command failed just return default return else ! Command did not return an error so try to read expected output file open ( file = temp_filename , newunit = unit , iostat = stat ) if ( stat == 0 ) then ! Read file into a scratch variable until status of doing so is checked call getline ( unit , temp_value , stat , iomsg ) if ( stat == 0 . and . temp_value /= '' ) then ! Return output from successful command returned = temp_value endif endif ! Always do the CLOSE because a failed open has unpredictable results. ! Add IOSTAT so a failed close does not cause program to stop close ( unit , status = \"delete\" , iostat = stat ) endif endif end function git_metadata subroutine create_verified_basic_manifest ( filename ) !> create a basic but verified default manifest file use fpm_toml , only : toml_table , toml_serialize , set_value use fpm_manifest_package , only : package_config_t , new_package use fpm_error , only : error_t implicit none character ( len =* ), intent ( in ) :: filename type ( toml_table ) :: table type ( package_config_t ) :: package type ( error_t ), allocatable :: error integer :: lun character ( len = 8 ) :: date character (:), allocatable :: output if ( exists ( filename )) then write ( stderr , '(*(g0,1x))' ) ' ' , filename ,& & 'already exists. Not overwriting' return endif !> get date to put into metadata in manifest file \"fpm.toml\" call date_and_time ( DATE = date ) table = toml_table () call fileopen ( filename , lun ) ! fileopen stops on error call set_value ( table , \"name\" , BNAME ) call set_value ( table , \"version\" , \"0.1.0\" ) call set_value ( table , \"license\" , \"license\" ) call set_value ( table , \"author\" , git_metadata ( 'uname' )) call set_value ( table , \"maintainer\" , git_metadata ( 'email' )) call set_value ( table , \"copyright\" , 'Copyright ' // date ( 1 : 4 ) // ', ' // git_metadata ( 'uname' )) ! continue building of manifest ! ... call new_package ( package , table , error = error ) if ( allocated ( error )) call fpm_stop ( 3 , '' ) output = toml_serialize ( table ) if ( settings % verbose ) then print '(a)' , output endif write ( lun , '(a)' ) output call fileclose ( lun ) ! fileopen stops on error end subroutine create_verified_basic_manifest subroutine validate_toml_data ( input ) !> verify a string array is a valid fpm.toml file ! use tomlf , only : toml_load use fpm_toml , only : toml_table , toml_serialize implicit none character ( kind = tfc , len = :), intent ( in ), allocatable :: input (:) character ( len = 1 ), parameter :: nl = new_line ( 'a' ) type ( toml_table ), allocatable :: table character ( kind = tfc , len = :), allocatable :: joined_string ! you have to add a newline character by using the intrinsic ! function `new_line(\"a\")` to get the lines processed correctly. joined_string = join ( input , right = nl ) if ( allocated ( table )) deallocate ( table ) call toml_load ( table , joined_string ) if ( allocated ( table )) then if ( settings % verbose ) then ! If the TOML file is successfully parsed the table will be allocated and ! can be written by `toml_serialize` to the standard output print '(a)' , toml_serialize ( table ) endif call table % destroy endif end subroutine validate_toml_data end subroutine cmd_new","tags":"","loc":"proc/cmd_new.html"},{"title":"is_meta_package – Fortran-lang/fpm","text":"public function is_meta_package(key) Check local schema for allowed entries Supported metapackages Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: key Instance of the TOML data structure Return Value logical Source Code logical function is_meta_package ( key ) !> Instance of the TOML data structure character ( * ), intent ( in ) :: key select case ( key ) !> Supported metapackages case ( \"openmp\" , \"stdlib\" , \"mpi\" , \"minpack\" , \"hdf5\" ) is_meta_package = . true . case default is_meta_package = . false . end select end function is_meta_package","tags":"","loc":"proc/is_meta_package.html"},{"title":"new_meta_config – Fortran-lang/fpm","text":"public subroutine new_meta_config(self, table, meta_allowed, error) Construct a new build configuration from a TOML data structure The toml table is not checked here because it already passed\nthe “new_dependencies” check Arguments Type Intent Optional Attributes Name type( metapackage_config_t ), intent(out) :: self Instance of the build configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure logical, intent(in) :: meta_allowed (:) List of keys allowed to be metapackages type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_meta_config ( self , table , meta_allowed , error ) !> Instance of the build configuration type ( metapackage_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys allowed to be metapackages logical , intent ( in ) :: meta_allowed (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat !> The toml table is not checked here because it already passed !> the \"new_dependencies\" check call new_meta_request ( self % openmp , \"openmp\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % stdlib , \"stdlib\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % minpack , \"minpack\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % mpi , \"mpi\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % hdf5 , \"hdf5\" , table , meta_allowed , error ) if ( allocated ( error )) return end subroutine new_meta_config","tags":"","loc":"proc/new_meta_config.html"},{"title":"new_meta_request – Fortran-lang/fpm","text":"public subroutine new_meta_request(self, key, table, meta_allowed, error) Construct a new metapackage request from the dependencies table Set name\nThe toml table is not checked here because it already passed\nthe “new_dependencies” check Set list of entries that are allowed to be metapackages Arguments Type Intent Optional Attributes Name type( metapackage_request_t ), intent(out) :: self character(len=*), intent(in) :: key The package name type(toml_table), intent(inout) :: table Instance of the TOML data structure logical, intent(in), optional :: meta_allowed (:) List of keys allowed to be metapackages type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_meta_request ( self , key , table , meta_allowed , error ) type ( metapackage_request_t ), intent ( out ) :: self !> The package name character ( len =* ), intent ( in ) :: key !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys allowed to be metapackages logical , intent ( in ), optional :: meta_allowed (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , i character ( len = :), allocatable :: value logical , allocatable :: allow_meta (:) type ( toml_key ), allocatable :: keys (:) call request_destroy ( self ) !> Set name self % name = key if (. not . is_meta_package ( key )) then call fatal_error ( error , \"Error reading fpm.toml: <\" // key // \"> is not a valid metapackage name\" ) return end if !> The toml table is not checked here because it already passed !> the \"new_dependencies\" check call table % get_keys ( keys ) !> Set list of entries that are allowed to be metapackages if ( present ( meta_allowed )) then if ( size ( meta_allowed ) /= size ( keys )) then call fatal_error ( error , \"Internal error: list of metapackage-enable entries does not match table size\" ) return end if allow_meta = meta_allowed else allocate ( allow_meta ( size ( keys )), source = . true .) endif do i = 1 , size ( keys ) ! Skip standard dependencies if (. not . allow_meta ( i )) cycle if ( keys ( i )% key == key ) then call get_value ( table , key , value ) if (. not . allocated ( value )) then call syntax_error ( error , \"Could not retrieve version string for metapackage key <\" // key // \">. Check syntax\" ) return else call request_parse ( self , value , error ) return endif end if end do ! Key is not present, metapackage not requested return end subroutine new_meta_request","tags":"","loc":"proc/new_meta_request.html"},{"title":"build_model – Fortran-lang/fpm","text":"public subroutine build_model(model, settings, package, error) Constructs a valid fpm model from command line settings and the toml manifest.\nAdd this dependency’s manifest macros Add this dependency’s package-level macros Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(out) :: model class( fpm_build_settings ), intent(inout) :: settings type( package_config_t ), intent(inout) :: package type( error_t ), intent(out), allocatable :: error Source Code subroutine build_model ( model , settings , package , error ) type ( fpm_model_t ), intent ( out ) :: model class ( fpm_build_settings ), intent ( inout ) :: settings type ( package_config_t ), intent ( inout ) :: package type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j type ( package_config_t ) :: dependency character ( len = :), allocatable :: manifest , lib_dir logical :: has_cpp logical :: duplicates_found type ( string_t ) :: include_dir model % package_name = package % name allocate ( model % include_dirs ( 0 )) allocate ( model % link_libraries ( 0 )) allocate ( model % external_modules ( 0 )) call new_compiler ( model % compiler , settings % compiler , settings % c_compiler , & & settings % cxx_compiler , echo = settings % verbose , verbose = settings % verbose ) call new_archiver ( model % archiver , settings % archiver , & & echo = settings % verbose , verbose = settings % verbose ) if ( model % compiler % is_unknown ()) then write ( * , '(*(a:,1x))' ) & \"\" , \"Unknown compiler\" , model % compiler % fc , \"requested!\" , & \"Defaults for this compiler might be incorrect\" end if call new_compiler_flags ( model , settings ) model % build_prefix = join_path ( \"build\" , basename ( model % compiler % fc )) model % include_tests = settings % build_tests model % enforce_module_names = package % build % module_naming model % module_prefix = package % build % module_prefix ! Resolve meta-dependencies into the package and the model call resolve_metapackages ( model , package , settings , error ) if ( allocated ( error )) return ! Create dependencies call new_dependency_tree ( model % deps , cache = join_path ( \"build\" , \"cache.toml\" )) ! Build and resolve model dependencies call model % deps % add ( package , error ) if ( allocated ( error )) return ! Update dependencies where needed call model % deps % update ( error ) if ( allocated ( error )) return ! build/ directory should now exist if (. not . exists ( \"build/.gitignore\" )) then call filewrite ( join_path ( \"build\" , \".gitignore\" ),[ \"*\" ]) end if allocate ( model % packages ( model % deps % ndep )) has_cpp = . false . do i = 1 , model % deps % ndep associate ( dep => model % deps % dep ( i )) manifest = join_path ( dep % proj_dir , \"fpm.toml\" ) call get_package_data ( dependency , manifest , error , apply_defaults = . true .) if ( allocated ( error )) exit model % packages ( i )% name = dependency % name associate ( features => model % packages ( i )% features ) features % implicit_typing = dependency % fortran % implicit_typing features % implicit_external = dependency % fortran % implicit_external features % source_form = dependency % fortran % source_form end associate model % packages ( i )% version = package % version % s () !> Add this dependency's manifest macros call model % packages ( i )% preprocess % destroy () if ( allocated ( dependency % preprocess )) then do j = 1 , size ( dependency % preprocess ) call model % packages ( i )% preprocess % add_config ( dependency % preprocess ( j )) end do end if !> Add this dependency's package-level macros if ( allocated ( dep % preprocess )) then do j = 1 , size ( dep % preprocess ) call model % packages ( i )% preprocess % add_config ( dep % preprocess ( j )) end do end if if ( model % packages ( i )% preprocess % is_cpp ()) has_cpp = . true . if (. not . allocated ( model % packages ( i )% sources )) allocate ( model % packages ( i )% sources ( 0 )) if ( allocated ( dependency % library )) then if ( allocated ( dependency % library % source_dir )) then lib_dir = join_path ( dep % proj_dir , dependency % library % source_dir ) if ( is_dir ( lib_dir )) then call add_sources_from_dir ( model % packages ( i )% sources , lib_dir , FPM_SCOPE_LIB , & with_f_ext = model % packages ( i )% preprocess % suffixes , error = error ) if ( allocated ( error )) exit end if end if if ( allocated ( dependency % library % include_dir )) then do j = 1 , size ( dependency % library % include_dir ) include_dir % s = join_path ( dep % proj_dir , dependency % library % include_dir ( j )% s ) if ( is_dir ( include_dir % s )) then model % include_dirs = [ model % include_dirs , include_dir ] end if end do end if end if if ( allocated ( dependency % build % link )) then model % link_libraries = [ model % link_libraries , dependency % build % link ] end if if ( allocated ( dependency % build % external_modules )) then model % external_modules = [ model % external_modules , dependency % build % external_modules ] end if ! Copy naming conventions from this dependency's manifest model % packages ( i )% enforce_module_names = dependency % build % module_naming model % packages ( i )% module_prefix = dependency % build % module_prefix end associate end do if ( allocated ( error )) return ! Add optional flags if ( has_cpp ) call set_cpp_preprocessor_flags ( model % compiler % id , model % fortran_compile_flags ) ! Add sources from executable directories if ( is_dir ( 'app' ) . and . package % build % auto_executables ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'app' , FPM_SCOPE_APP , & with_executables = . true ., with_f_ext = model % packages ( 1 )% preprocess % suffixes ,& error = error ) if ( allocated ( error )) then return end if end if if ( is_dir ( 'example' ) . and . package % build % auto_examples ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'example' , FPM_SCOPE_EXAMPLE , & with_executables = . true ., & with_f_ext = model % packages ( 1 )% preprocess % suffixes , error = error ) if ( allocated ( error )) then return end if end if if ( is_dir ( 'test' ) . and . package % build % auto_tests ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'test' , FPM_SCOPE_TEST , & with_executables = . true ., & with_f_ext = model % packages ( 1 )% preprocess % suffixes , error = error ) if ( allocated ( error )) then return endif end if if ( allocated ( package % executable )) then call add_executable_sources ( model % packages ( 1 )% sources , package % executable , FPM_SCOPE_APP , & auto_discover = package % build % auto_executables , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return end if end if if ( allocated ( package % example )) then call add_executable_sources ( model % packages ( 1 )% sources , package % example , FPM_SCOPE_EXAMPLE , & auto_discover = package % build % auto_examples , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return end if end if if ( allocated ( package % test )) then call add_executable_sources ( model % packages ( 1 )% sources , package % test , FPM_SCOPE_TEST , & auto_discover = package % build % auto_tests , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return endif endif if ( settings % verbose ) then write ( * , * ) ' BUILD_NAME: ' , model % build_prefix write ( * , * ) ' COMPILER: ' , model % compiler % fc write ( * , * ) ' C COMPILER: ' , model % compiler % cc write ( * , * ) ' CXX COMPILER: ' , model % compiler % cxx write ( * , * ) ' COMPILER OPTIONS: ' , model % fortran_compile_flags write ( * , * ) ' C COMPILER OPTIONS: ' , model % c_compile_flags write ( * , * ) ' CXX COMPILER OPTIONS: ' , model % cxx_compile_flags write ( * , * ) ' LINKER OPTIONS: ' , model % link_flags write ( * , * ) ' INCLUDE DIRECTORIES: [' , string_cat ( model % include_dirs , ',' ), ']' end if ! Check for invalid module names call check_module_names ( model , error ) if ( allocated ( error )) return ! Check for duplicate modules duplicates_found = . false . call check_modules_for_duplicates ( model , duplicates_found ) if ( duplicates_found ) then call fpm_stop ( 1 , '*build_model*:Error: One or more duplicate module names found.' ) end if end subroutine build_model","tags":"","loc":"proc/build_model.html"},{"title":"check_modules_for_duplicates – Fortran-lang/fpm","text":"public subroutine check_modules_for_duplicates(model, duplicates_found) Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(in) :: model logical :: duplicates_found Source Code subroutine check_modules_for_duplicates ( model , duplicates_found ) type ( fpm_model_t ), intent ( in ) :: model integer :: maxsize integer :: i , j , k , l , m , modi type ( string_t ), allocatable :: modules (:) logical :: duplicates_found ! Initialise the size of array maxsize = 0 ! Get number of modules provided by each source file of every package do i = 1 , size ( model % packages ) do j = 1 , size ( model % packages ( i )% sources ) if ( allocated ( model % packages ( i )% sources ( j )% modules_provided )) then maxsize = maxsize + size ( model % packages ( i )% sources ( j )% modules_provided ) end if end do end do ! Allocate array to contain distinct names of modules allocate ( modules ( maxsize )) ! Initialise index to point at start of the newly allocated array modi = 1 ! Loop through modules provided by each source file of every package ! Add it to the array if it is not already there ! Otherwise print out warning about duplicates do k = 1 , size ( model % packages ) do l = 1 , size ( model % packages ( k )% sources ) if ( allocated ( model % packages ( k )% sources ( l )% modules_provided )) then do m = 1 , size ( model % packages ( k )% sources ( l )% modules_provided ) if ( model % packages ( k )% sources ( l )% modules_provided ( m )% s . in . modules (: modi - 1 )) then write ( stderr , * ) \"Warning: Module \" , model % packages ( k )% sources ( l )% modules_provided ( m )% s , & \" in \" , model % packages ( k )% sources ( l )% file_name , \" is a duplicate\" duplicates_found = . true . else modules ( modi ) = model % packages ( k )% sources ( l )% modules_provided ( m ) modi = modi + 1 end if end do end if end do end do end subroutine check_modules_for_duplicates","tags":"","loc":"proc/check_modules_for_duplicates.html"},{"title":"cmd_build – Fortran-lang/fpm","text":"public subroutine cmd_build(settings) Dump model to file Arguments Type Intent Optional Attributes Name type( fpm_build_settings ), intent(inout) :: settings Source Code subroutine cmd_build ( settings ) type ( fpm_build_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( error_t ), allocatable :: error integer :: i call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Package error: ' // error % message ) end if call build_model ( model , settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Model error: ' // error % message ) end if call targets_from_sources ( targets , model , settings % prune , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Target error: ' // error % message ) end if !> Dump model to file if ( len_trim ( settings % dump ) > 0 ) then call model % dump ( trim ( settings % dump ), error , json = name_is_json ( trim ( settings % dump ))) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_build* Model dump error: ' // error % message ) endif if ( settings % list ) then do i = 1 , size ( targets ) write ( stderr , * ) targets ( i )% ptr % output_file enddo else if ( settings % show_model ) then call show_model ( model ) else call build_package ( targets , model , verbose = settings % verbose ) endif end subroutine cmd_build","tags":"","loc":"proc/cmd_build.html"},{"title":"cmd_clean – Fortran-lang/fpm","text":"public subroutine cmd_clean(settings) Delete the build directory including or excluding dependencies. Can be used\nto clear the registry cache. Arguments Type Intent Optional Attributes Name class( fpm_clean_settings ), intent(in) :: settings Settings for the clean command. Source Code subroutine cmd_clean ( settings ) !> Settings for the clean command. class ( fpm_clean_settings ), intent ( in ) :: settings character :: user_response type ( fpm_global_settings ) :: global_settings type ( error_t ), allocatable :: error ! Clear registry cache if ( settings % registry_cache ) then call get_global_settings ( global_settings , error ) if ( allocated ( error )) return call os_delete_dir ( os_is_unix (), global_settings % registry_settings % cache_path ) end if if ( is_dir ( 'build' )) then ! Remove the entire build directory if ( settings % clean_all ) then call os_delete_dir ( os_is_unix (), 'build' ); return ! Remove the build directory but skip dependencies else if ( settings % clean_skip ) then call delete_skip ( os_is_unix ()); return end if ! Prompt to remove the build directory but skip dependencies write ( stdout , '(A)' , advance = 'no' ) \"Delete build, excluding dependencies (y/n)? \" read ( stdin , '(A1)' ) user_response if ( lower ( user_response ) == 'y' ) call delete_skip ( os_is_unix ()) else write ( stdout , '(A)' ) \"fpm: No build directory found.\" end if end subroutine cmd_clean","tags":"","loc":"proc/cmd_clean.html"},{"title":"cmd_run – Fortran-lang/fpm","text":"public subroutine cmd_run(settings, test) Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(inout) :: settings logical, intent(in) :: test Source Code subroutine cmd_run ( settings , test ) class ( fpm_run_settings ), intent ( inout ) :: settings logical , intent ( in ) :: test integer :: i , j , col_width logical :: found ( size ( settings % name )) type ( error_t ), allocatable :: error type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( string_t ) :: exe_cmd type ( string_t ), allocatable :: executables (:) type ( build_target_t ), pointer :: exe_target type ( srcfile_t ), pointer :: exe_source integer :: run_scope , firsterror integer , allocatable :: stat (:), target_ID (:) character ( len = :), allocatable :: line call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Package error: ' // error % message ) end if call build_model ( model , settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Model error: ' // error % message ) end if call targets_from_sources ( targets , model , settings % prune , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Targets error: ' // error % message ) end if if ( test ) then run_scope = FPM_SCOPE_TEST else run_scope = merge ( FPM_SCOPE_EXAMPLE , FPM_SCOPE_APP , settings % example ) end if ! Enumerate executable targets to run col_width = - 1 found (:) = . false . allocate ( executables ( size ( targets )), target_ID ( size ( targets ))) enumerate : do i = 1 , size ( targets ) exe_target => targets ( i )% ptr if ( should_be_run ( settings , run_scope , exe_target )) then exe_source => exe_target % dependencies ( 1 )% ptr % source col_width = max ( col_width , len ( basename ( exe_target % output_file )) + 2 ) ! Priority by name ID, or 0 if no name present (run first) j = settings % name_ID ( exe_source % exe_name ) target_ID ( i ) = j if ( j > 0 ) found ( j ) = . true . exe_cmd % s = exe_target % output_file executables ( i ) = exe_cmd else target_ID ( i ) = huge ( target_ID ( i )) endif end do enumerate ! sort executables by ascending name ID, resize call sort_executables ( target_ID , executables ) ! Check if any apps/tests were found if ( col_width < 0 ) then if ( test ) then call fpm_stop ( 0 , 'No tests to run' ) else call fpm_stop ( 0 , 'No executables to run' ) end if end if ! Check all names are valid ! or no name and found more than one file if ( any (. not . found ) ) then line = join ( settings % name ) if ( line /= '.' ) then ! do not report these special strings if ( any (. not . found )) then write ( stderr , '(A)' , advance = \"no\" ) '*cmd_run*:specified names ' do j = 1 , size ( settings % name ) if (. not . found ( j )) write ( stderr , '(A)' , advance = \"no\" ) '\"' // trim ( settings % name ( j )) // '\" ' end do write ( stderr , '(A)' ) 'not found.' write ( stderr , * ) else if ( settings % verbose ) then write ( stderr , '(A)' , advance = \"yes\" ) 'when more than one executable is available' write ( stderr , '(A)' , advance = \"yes\" ) ' program names must be specified.' endif endif call compact_list_all () if ( line == '.' . or . line == ' ' ) then ! do not report these special strings call fpm_stop ( 0 , '' ) else call fpm_stop ( 1 , '' ) endif end if call build_package ( targets , model , verbose = settings % verbose ) if ( settings % list ) then call compact_list () else allocate ( stat ( size ( executables ))) do i = 1 , size ( executables ) if ( exists ( executables ( i )% s )) then if ( settings % runner /= ' ' ) then if (. not . allocated ( settings % args )) then call run ( settings % runner_command () // ' ' // executables ( i )% s , & echo = settings % verbose , exitstat = stat ( i )) else call run ( settings % runner_command () // ' ' // executables ( i )% s // \" \" // settings % args , & echo = settings % verbose , exitstat = stat ( i )) endif else if (. not . allocated ( settings % args )) then call run ( executables ( i )% s , echo = settings % verbose , exitstat = stat ( i )) else call run ( executables ( i )% s // \" \" // settings % args , echo = settings % verbose , & exitstat = stat ( i )) endif endif else call fpm_stop ( 1 , '*cmd_run*:' // executables ( i )% s // ' not found' ) end if end do if ( any ( stat /= 0 )) then do i = 1 , size ( stat ) if ( stat ( i ) /= 0 ) then write ( stderr , '(*(g0:,1x))' ) ' Execution for object \"' , basename ( executables ( i )% s ),& '\" returned exit code ' , stat ( i ) end if end do firsterror = findloc ( stat /= 0 , value = . true ., dim = 1 ) call fpm_stop ( stat ( firsterror ), '*cmd_run*:stopping due to failed executions' ) end if end if contains subroutine compact_list_all () integer , parameter :: LINE_WIDTH = 80 integer :: ii , jj , nCol jj = 1 nCol = LINE_WIDTH / col_width write ( stderr , * ) 'Available names:' do ii = 1 , size ( targets ) exe_target => targets ( ii )% ptr if ( exe_target % target_type == FPM_TARGET_EXECUTABLE . and . & allocated ( exe_target % dependencies )) then exe_source => exe_target % dependencies ( 1 )% ptr % source if ( exe_source % unit_scope == run_scope ) then write ( stderr , '(A)' , advance = ( merge ( \"yes\" , \"no \" , modulo ( jj , nCol ) == 0 ))) & & [ character ( len = col_width ) :: basename ( exe_target % output_file , suffix = . false .)] jj = jj + 1 end if end if end do write ( stderr , * ) end subroutine compact_list_all subroutine compact_list () integer , parameter :: LINE_WIDTH = 80 integer :: ii , jj , nCol jj = 1 nCol = LINE_WIDTH / col_width write ( stderr , * ) 'Matched names:' do ii = 1 , size ( executables ) write ( stderr , '(A)' , advance = ( merge ( \"yes\" , \"no \" , modulo ( jj , nCol ) == 0 ))) & & [ character ( len = col_width ) :: basename ( executables ( ii )% s , suffix = . false .)] jj = jj + 1 end do write ( stderr , * ) end subroutine compact_list end subroutine cmd_run","tags":"","loc":"proc/cmd_run.html"},{"title":"cmd_export – Fortran-lang/fpm","text":"public subroutine cmd_export(settings) Entry point for the export subcommand\nRead in manifest\nExport manifest\nExport dependency tree Generate dependency tree\nExport dependency tree\nExport full model Arguments Type Intent Optional Attributes Name type( fpm_export_settings ), intent(inout) :: settings Representation of the command line arguments Source Code subroutine cmd_export ( settings ) !> Representation of the command line arguments type ( fpm_export_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( dependency_tree_t ) :: deps type ( fpm_model_t ) :: model type ( error_t ), allocatable :: error integer :: ii character ( len = :), allocatable :: filename if ( len_trim ( settings % dump_manifest ) <= 0 . and . & len_trim ( settings % dump_model ) <= 0 . and . & len_trim ( settings % dump_dependencies ) <= 0 ) then call fpm_stop ( 0 , '*cmd_export* exiting: no manifest/model/dependencies keyword provided' ) end if !> Read in manifest call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) !> Export manifest if ( len_trim ( settings % dump_manifest ) > 0 ) then filename = trim ( settings % dump_manifest ) call package % dump ( filename , error , json = name_is_json ( filename )) end if !> Export dependency tree if ( len_trim ( settings % dump_dependencies ) > 0 ) then !> Generate dependency tree filename = join_path ( \"build\" , \"cache.toml\" ) call new_dependency_tree ( deps , cache = filename , verbosity = merge ( 2 , 1 , settings % verbose )) call deps % add ( package , error ) call handle_error ( error ) !> Export dependency tree filename = settings % dump_dependencies call deps % dump ( filename , error , json = name_is_json ( filename )) call handle_error ( error ) end if !> Export full model if ( len_trim ( settings % dump_model ) > 0 ) then call build_model ( model , settings % fpm_build_settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_export* Model error: ' // error % message ) end if filename = settings % dump_model call model % dump ( filename , error , json = name_is_json ( filename )) call handle_error ( error ) end if end subroutine cmd_export","tags":"","loc":"proc/cmd_export.html"},{"title":"new_package – Fortran-lang/fpm","text":"public subroutine new_package(self, table, root, error) Construct a new package configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( package_config_t ), intent(out) :: self Instance of the package configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_package ( self , table , root , error ) !> Instance of the package configuration type ( package_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( len =* ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error ! Backspace (8), tabulator (9), newline (10), formfeed (12) and carriage ! return (13) are invalid in package names character ( len =* ), parameter :: invalid_chars = & achar ( 8 ) // achar ( 9 ) // achar ( 10 ) // achar ( 12 ) // achar ( 13 ) type ( toml_table ), pointer :: child , node type ( toml_array ), pointer :: children character ( len = :), allocatable :: version , version_file integer :: ii , nn , stat , io call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve package name\" ) return end if if ( bad_name_error ( error , 'package' , self % name )) then return endif call get_value ( table , \"license\" , self % license ) call get_value ( table , \"author\" , self % author ) call get_value ( table , \"maintainer\" , self % maintainer ) call get_value ( table , \"copyright\" , self % copyright ) if ( len ( self % name ) <= 0 ) then call syntax_error ( error , \"Package name must be a non-empty string\" ) return end if ii = scan ( self % name , invalid_chars ) if ( ii > 0 ) then call syntax_error ( error , \"Package name contains invalid characters\" ) return end if call get_value ( table , \"build\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for build entry, must be a table\" ) return end if call new_build_config ( self % build , child , self % name , error ) if ( allocated ( error )) return call get_value ( table , \"install\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for install entry, must be a table\" ) return end if call new_install_config ( self % install , child , error ) if ( allocated ( error )) return call get_value ( table , \"fortran\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for fortran entry, must be a table\" ) return end if call new_fortran_config ( self % fortran , child , error ) if ( allocated ( error )) return call get_value ( table , \"version\" , version , \"0\" ) call new_version ( self % version , version , error ) if ( allocated ( error ) . and . present ( root )) then version_file = join_path ( root , version ) if ( exists ( version_file )) then deallocate ( error ) open ( file = version_file , newunit = io , iostat = stat ) if ( stat == 0 ) then call getline ( io , version , iostat = stat ) end if if ( stat == 0 ) then close ( io , iostat = stat ) end if if ( stat == 0 ) then call new_version ( self % version , version , error ) else call fatal_error ( error , \"Reading version number from file '\" & & // version_file // \"' failed\" ) end if end if end if if ( allocated ( error )) return call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , root , self % meta , error ) if ( allocated ( error )) return end if call get_value ( table , \"dev-dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dev_dependency , child , root , error = error ) if ( allocated ( error )) return end if call get_value ( table , \"library\" , child , requested = . false .) if ( associated ( child )) then allocate ( self % library ) call new_library ( self % library , child , error ) if ( allocated ( error )) return end if call get_value ( table , \"profiles\" , child , requested = . false .) if ( associated ( child )) then call new_profiles ( self % profiles , child , error ) if ( allocated ( error )) return else self % profiles = get_default_profiles ( error ) if ( allocated ( error )) return end if call get_value ( table , \"executable\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % executable ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve executable from array entry\" ) exit end if call new_executable ( self % executable ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % executable , error ) if ( allocated ( error )) return end if call get_value ( table , \"example\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % example ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve example from array entry\" ) exit end if call new_example ( self % example ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % example , error ) if ( allocated ( error )) return if ( allocated ( self % executable )) then call unique_programs ( self % executable , self % example , error ) if ( allocated ( error )) return end if end if call get_value ( table , \"test\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % test ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve test from array entry\" ) exit end if call new_test ( self % test ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % test , error ) if ( allocated ( error )) return end if call get_value ( table , \"preprocess\" , child , requested = . false .) if ( associated ( child )) then call new_preprocessors ( self % preprocess , child , error ) if ( allocated ( error )) return end if end subroutine new_package","tags":"","loc":"proc/new_package.html"},{"title":"build_progress_t – Fortran-lang/fpm","text":"public interface build_progress_t Constructor for build_progress_t Module Procedures private function new_build_progress(target_queue, plain_mode) result(progress) Initialise a new build progress object Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in), target :: target_queue (:) The queue of scheduled targets logical, intent(in), optional :: plain_mode Enable ‘plain’ output for progress object Return Value type( build_progress_t ) Progress object to initialise","tags":"","loc":"interface/build_progress_t.html"},{"title":"new_build_config – Fortran-lang/fpm","text":"public subroutine new_build_config(self, table, package_name, error) Construct a new build configuration from a TOML data structure Module naming: fist, attempt boolean value first Value found, but not a boolean. Attempt to read a prefix string Arguments Type Intent Optional Attributes Name type( build_config_t ), intent(out) :: self Instance of the build configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: package_name Package name type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_build_config ( self , table , package_name , error ) !> Instance of the build configuration type ( build_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Package name character ( len =* ), intent ( in ) :: package_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat call check ( table , package_name , error ) if ( allocated ( error )) return call get_value ( table , \"auto-executables\" , self % auto_executables , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-executables' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"auto-tests\" , self % auto_tests , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-tests' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"auto-examples\" , self % auto_examples , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-examples' in fpm.toml, expecting logical\" ) return end if !> Module naming: fist, attempt boolean value first call get_value ( table , \"module-naming\" , self % module_naming , . false ., stat = stat ) if ( stat == toml_stat % success ) then ! Boolean value found. Set no custom prefix. This also falls back to key not provided if ( allocated ( self % module_prefix % s )) deallocate ( self % module_prefix % s ) else !> Value found, but not a boolean. Attempt to read a prefix string call get_value ( table , \"module-naming\" , self % module_prefix % s ) if (. not . allocated ( self % module_prefix % s )) then call syntax_error ( error , \"Could not read value for 'module-naming' in fpm.toml, expecting logical or a string\" ) return end if if (. not . is_valid_module_prefix ( self % module_prefix )) then call syntax_error ( error , \"Invalid custom module name prefix for in fpm.toml: <\" // self % module_prefix % s // & \">, expecting a valid alphanumeric string\" ) return end if ! Set module naming to ON self % module_naming = . true . end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return call get_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return end subroutine new_build_config","tags":"","loc":"proc/new_build_config.html"},{"title":"new_test – Fortran-lang/fpm","text":"public subroutine new_test(self, table, error) Construct a new test configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( test_config_t ), intent(out) :: self Instance of the test configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_test ( self , table , error ) !> Instance of the test configuration type ( test_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve test name\" ) return end if if ( bad_name_error ( error , 'test' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"test\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_test","tags":"","loc":"proc/new_test.html"},{"title":"fpm_manifest – Fortran-lang/fpm","text":"Package configuration data. This module provides the necessary procedure to translate a TOML document\nto the corresponding Fortran type, while verifying it with respect to\nits schema. Additionally, the required data types for users of this module are reexported\nto hide the actual implementation details. Uses fpm_manifest_package fpm_toml fpm_manifest_library fpm_environment fpm_manifest_dependency fpm_manifest_test fpm_error fpm_filesystem fpm_strings fpm_manifest_example fpm_manifest_executable fpm_manifest_preprocess Subroutines public subroutine default_example (self, name) Populate test in case we find the default example/ directory Arguments Type Intent Optional Attributes Name type( example_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package public subroutine default_executable (self, name) Populate executable in case we find the default app directory Arguments Type Intent Optional Attributes Name type( executable_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package public subroutine default_library (self) Populate library in case we find the default src directory Arguments Type Intent Optional Attributes Name type( library_config_t ), intent(out) :: self Instance of the library meta data public subroutine default_test (self, name) Populate test in case we find the default test/ directory Arguments Type Intent Optional Attributes Name type( test_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package public subroutine get_package_data (package, file, error, apply_defaults) Obtain package meta data from a configuation file Arguments Type Intent Optional Attributes Name type( package_config_t ), intent(out) :: package Parsed package meta data character(len=*), intent(in) :: file Name of the package configuration file type( error_t ), intent(out), allocatable :: error Error status of the operation logical, intent(in), optional :: apply_defaults Apply package defaults (uses file system operations)","tags":"","loc":"module/fpm_manifest.html"},{"title":"fpm_manifest_install – Fortran-lang/fpm","text":"Implementation of the installation configuration. An install table can currently have the following fields library = bool Uses fpm_toml fpm_error Derived Types type, public, extends( serializable_t ) :: install_config_t Configuration data for installation Components Type Visibility Attributes Name Initial logical, public :: library = .false. Install library with this project Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => install_conf_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_install_config (self, table, error) Create a new installation configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( install_config_t ), intent(out) :: self Instance of the install configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_install.html"},{"title":"fpm_targets – Fortran-lang/fpm","text":"Build target handling This module handles the construction of the build target list\n from the sources list ( [[targets_from_sources]] ), the\n resolution of module-dependencies between build targets\n ( [[resolve_module_dependencies]] ), and the enumeration of\n objects required for link targets ( [[resolve_target_linking]] ). A build target ( [[build_target_t]] ) is a file to be generated\n by the backend (compilation and linking). @note Note\n The current implementation is ignorant to the existence of\n module files ( .mod , .smod ). Dependencies arising from modules\n are based on the corresponding object files ( .o ) only. For more information, please read the documentation for the procedures: [[build_target_list]] [[resolve_module_dependencies]] Enumerations Target type: FPM_TARGET_* Describes the type of build target — determines backend build rules Uses fpm_environment fpm_sources fpm_manifest_preprocess fpm_filesystem fpm_strings fpm_compiler iso_fortran_env fpm_error fpm_model Variables Type Visibility Attributes Name Initial integer, public, parameter :: FPM_TARGET_ARCHIVE = 2 Target type is library archive integer, public, parameter :: FPM_TARGET_CPP_OBJECT = 5 Target type is cpp compiled object integer, public, parameter :: FPM_TARGET_C_OBJECT = 4 Target type is c compiled object integer, public, parameter :: FPM_TARGET_EXECUTABLE = 1 Target type is executable integer, public, parameter :: FPM_TARGET_OBJECT = 3 Target type is compiled object integer, public, parameter :: FPM_TARGET_UNKNOWN = -1 Target type is unknown (ignored) Derived Types type, public :: build_target_ptr Wrapper type for constructing arrays of [[build_target_t]] pointers Components Type Visibility Attributes Name Initial type( build_target_t ), public, pointer :: ptr => null() type, public :: build_target_t Type describing a generated build target Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: compile_flags Compile flags for this build target type( build_target_ptr ), public, allocatable :: dependencies (:) Resolved build dependencies integer(kind=int64), public, allocatable :: digest_cached Previous source file hash type( fortran_features_t ), public :: features Language features character(len=:), public, allocatable :: link_flags Link flags for this build target type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public, allocatable :: link_objects (:) Objects needed to link this target type( string_t ), public, allocatable :: macros (:) List of macros character(len=:), public, allocatable :: output_dir File path of output directory character(len=:), public, allocatable :: output_file File path of build target object relative to cwd character(len=:), public, allocatable :: output_log_file File path of build log file relative to cwd character(len=:), public, allocatable :: output_name File path of build target object relative to output_dir character(len=:), public, allocatable :: package_name Name of parent package integer, public :: schedule = -1 Targets in the same schedule group are guaranteed to be independent logical, public :: skip = .false. Flag set if build target will be skipped (not built) logical, public :: sorted = .false. Flag set if build target is sorted for building type( srcfile_t ), public, allocatable :: source Primary source for this build target integer, public :: target_type = FPM_TARGET_UNKNOWN Target type logical, public :: touched = .false. Flag set when first visited to check for circular dependencies character(len=:), public, allocatable :: version Version number Type-Bound Procedures procedure, public :: is_executable_target Functions public pure function FPM_TARGET_NAME (type) result(msg) Target type name Arguments Type Intent Optional Attributes Name integer, intent(in) :: type Return Value character(len=:), allocatable Subroutines public subroutine add_dependency (target, dependency) Add pointer to dependeny in target%dependencies Arguments Type Intent Optional Attributes Name type( build_target_t ), intent(inout) :: target type( build_target_t ), intent(in), target :: dependency public subroutine add_target (targets, package, type, output_name, source, link_libraries, features, preprocess, version) Allocate a new target and append to target list Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout), allocatable :: targets (:) character(len=*), intent(in) :: package integer, intent(in) :: type character(len=*), intent(in) :: output_name type( srcfile_t ), intent(in), optional :: source type( string_t ), intent(in), optional :: link_libraries (:) type( fortran_features_t ), intent(in), optional :: features type( preprocess_config_t ), intent(in), optional :: preprocess character(len=*), intent(in), optional :: version public subroutine filter_executable_targets (targets, scope, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) integer, intent(in) :: scope type( string_t ), intent(out), allocatable :: list (:) public subroutine filter_library_targets (targets, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) type( string_t ), intent(out), allocatable :: list (:) public subroutine filter_modules (targets, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) type( string_t ), intent(out), allocatable :: list (:) public subroutine resolve_module_dependencies (targets, external_modules, error) Add dependencies to source-based targets ( FPM_TARGET_OBJECT )\n based on any modules used by the corresponding source file. Read more… Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout), target :: targets (:) type( string_t ), intent(in) :: external_modules (:) type( error_t ), intent(out), allocatable :: error public subroutine targets_from_sources (targets, model, prune, error) High-level wrapper to generate build target information Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(out), allocatable :: targets (:) The generated list of build targets type( fpm_model_t ), intent(inout), target :: model The package model from which to construct the target list logical, intent(in) :: prune Enable tree-shaking/pruning of module dependencies type( error_t ), intent(out), allocatable :: error Error structure","tags":"","loc":"module/fpm_targets.html"},{"title":"fpm_manifest_profile – Fortran-lang/fpm","text":"Implementation of the meta data for compiler flag profiles. A profiles table can currently have the following subtables:\n Profile names - any string, if omitted, flags are appended to all matching profiles\n Compiler - any from the following list, omitting it yields an error “gfortran” “ifort” “ifx” “pgfortran” “nvfortran” “flang” “caf” “f95” “lfortran” “lfc” “nagfor” “crayftn” “xlf90” “ftn95” OS - any from the following list, if omitted, the profile is used if and only\n if there is no profile perfectly matching the current configuration “linux” “macos” “windows” “cygwin” “solaris” “freebsd” “openbsd” “unknown” Each of the subtables currently supports the following fields: [profiles.debug.gfortran.linux] flags = \"-Wall -g -Og\" c-flags = \"-g O1\" cxx-flags = \"-g O1\" link-time-flags = \"-xlinkopt\" files = { \"hello_world.f90\" = \"-Wall -O3\" } Uses fpm_environment fpm_toml fpm_strings fpm_error fpm_filesystem Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: DEFAULT_COMPILER = 'gfortran' Name of the default compiler integer, public, parameter :: OS_ALL = -1 character(len=:), public, allocatable :: path Derived Types type, public, extends( serializable_t ) :: file_scope_flag Type storing file name - file scope compiler flags pairs Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: file_name Name of the file character(len=:), public, allocatable :: flags File scope flags Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => file_scope_dump generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => file_scope_load generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => file_scope_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: profile_config_t Configuration meta data for a profile Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: c_flags C compiler flags character(len=:), public, allocatable :: compiler Name of the compiler character(len=:), public, allocatable :: cxx_flags C++ compiler flags type( file_scope_flag ), public, allocatable :: file_scope_flags (:) File scope flags character(len=:), public, allocatable :: flags Fortran compiler flags logical, public :: is_built_in = .false. Is this profile one of the built-in ones? character(len=:), public, allocatable :: link_time_flags Link time compiler flags integer, public :: os_type = OS_ALL Value repesenting OS character(len=:), public, allocatable :: profile_name Name of the profile Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => profile_dump procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => profile_load generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => profile_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public function file_scope_same (this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical public function get_default_profiles (error) result(default_profiles) Construct an array of built-in profiles Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Error handling Return Value type( profile_config_t ), allocatable, (:) public function info_profile (profile) result(s) Print a representation of profile_config_t Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(in) :: profile Profile to be represented Return Value character(len=:), allocatable String representation of given profile public function new_profile (profile_name, compiler, os_type, flags, c_flags, cxx_flags, link_time_flags, file_scope_flags, is_built_in) result(profile) Construct a new profile configuration from a TOML data structure Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: profile_name Name of the profile character(len=*), intent(in) :: compiler Name of the compiler integer, intent(in) :: os_type Type of the OS character(len=*), intent(in), optional :: flags Fortran compiler flags character(len=*), intent(in), optional :: c_flags C compiler flags character(len=*), intent(in), optional :: cxx_flags C++ compiler flags character(len=*), intent(in), optional :: link_time_flags Link time compiler flags type( file_scope_flag ), intent(in), optional :: file_scope_flags (:) File scope flags logical, intent(in), optional :: is_built_in Is this profile one of the built-in ones? Return Value type( profile_config_t ) public function os_type_name (os_type) Match lowercase string with name of OS to os_type enum Arguments Type Intent Optional Attributes Name integer, intent(in) :: os_type Enum representing type of OS Return Value character(len=:), allocatable Name of operating system public function profile_same (this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Subroutines public subroutine file_scope_dump (self, table, error) Dump to toml table Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine file_scope_load (self, table, error) Read from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine find_profile (profiles, profile_name, compiler, os_type, found_matching, chosen_profile) Look for profile with given configuration in array profiles Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(in), allocatable :: profiles (:) Array of profiles character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler Name of compiler integer, intent(in) :: os_type Type of operating system (enum) logical, intent(out) :: found_matching Boolean value containing true if matching profile was found type( profile_config_t ), intent(out) :: chosen_profile Last matching profile in the profiles array public subroutine get_flags (profile_name, compiler_name, os_type, key_list, table, profiles, profindex, os_valid) Look for flags, c-flags, link-time-flags key-val pairs\nand files table in a given table and create new profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler integer, intent(in) :: os_type OS type type(toml_key), intent(in), allocatable :: key_list (:) List of keys in the table type(toml_table), intent(in), pointer :: table Table containing OS tables type( profile_config_t ), intent(inout), allocatable :: profiles (:) List of profiles integer, intent(inout) :: profindex Index in the list of profiles logical, intent(in) :: os_valid Was called with valid operating system public subroutine info (self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: self Instance of the profile configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout public subroutine match_os_type (os_name, os_type) Match os_type enum to a lowercase string with name of OS Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: os_name Name of operating system integer, intent(out) :: os_type Enum representing type of OS public subroutine new_profiles (profiles, table, error) Construct new profiles array from a TOML data structure Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(out), allocatable :: profiles (:) Instance of the dependency configuration type(toml_table), intent(inout), target :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine profile_dump (self, table, error) Dump to toml table Read more… Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine profile_load (self, table, error) Read from toml table (no checks made at this stage) Read more… Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine traverse_compilers (profile_name, comp_list, table, error, profiles_size, profiles, profindex) Traverse compiler tables Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile type(toml_key), intent(in), allocatable :: comp_list (:) List of OSs in table with profile name given type(toml_table), intent(in), pointer :: table Table containing compiler tables type( error_t ), intent(out), allocatable :: error Error handling integer, intent(inout), optional :: profiles_size Number of profiles in list of profiles type( profile_config_t ), intent(inout), optional, allocatable :: profiles (:) List of profiles integer, intent(inout), optional :: profindex Index in the list of profiles public subroutine traverse_oss (profile_name, compiler_name, os_list, table, profiles, profindex, error) Traverse operating system tables to obtain profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: os_list (:) List of OSs in table with profile name and compiler name given type(toml_table), intent(in), pointer :: table Table containing OS tables type( profile_config_t ), intent(inout), allocatable :: profiles (:) List of profiles integer, intent(inout) :: profindex Index in the list of profiles type( error_t ), intent(out), allocatable :: error Error handling public subroutine traverse_oss_for_size (profile_name, compiler_name, os_list, table, profiles_size, error) Traverse operating system tables to obtain number of profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: os_list (:) List of OSs in table with profile name and compiler name given type(toml_table), intent(in), pointer :: table Table containing OS tables integer, intent(inout) :: profiles_size Number of profiles in list of profiles type( error_t ), intent(out), allocatable :: error Error handling public subroutine validate_compiler_name (compiler_name, is_valid) Check if compiler name is a valid compiler name Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: compiler_name Name of a compiler logical, intent(out) :: is_valid Boolean value of whether compiler_name is valid or not public subroutine validate_os_name (os_name, is_valid) Check if os_name is a valid name of a supported OS Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: os_name Name of an operating system logical, intent(out) :: is_valid Boolean value of whether os_name is valid or not public subroutine validate_profile_table (profile_name, compiler_name, key_list, table, error, os_valid) Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: key_list (:) List of keys in the table type(toml_table), intent(in), pointer :: table Table containing OS tables type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in) :: os_valid Was called with valid operating system","tags":"","loc":"module/fpm_manifest_profile.html"},{"title":"fpm_environment – Fortran-lang/fpm","text":"This module contains procedures that interact with the programming environment. [get_os_type] – Determine the OS type [get_env] – return the value of an environment variable Uses iso_c_binding fpm_error iso_fortran_env Variables Type Visibility Attributes Name Initial integer, public, parameter :: OS_CYGWIN = 4 integer, public, parameter :: OS_FREEBSD = 6 integer, public, parameter :: OS_LINUX = 1 integer, public, parameter :: OS_MACOS = 2 integer, public, parameter :: OS_OPENBSD = 7 integer, public, parameter :: OS_SOLARIS = 5 integer, public, parameter :: OS_UNKNOWN = 0 integer, public, parameter :: OS_WINDOWS = 3 Functions public pure function OS_NAME (os) Return string describing the OS type flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: os Return Value character(len=:), allocatable public function delete_env (name) result(success) Deletes an environment variable for the current environment using the C standard library\nReturns an error if the variable did not exist in the first place Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Variable name Return Value logical public function get_command_arguments_quoted () result(args) Arguments None Return Value character(len=:), allocatable public function get_env (NAME, DEFAULT) result(VALUE) get named environment variable value. It it is blank or\n not set return the optional default value\n!print , NAME, ” is not defined in the environment. Strange…”\n!print , “This processor doesn’t support environment variables. Boooh!” Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: NAME name of environment variable to get the value of character(len=*), intent(in), optional :: DEFAULT default value to return if the requested value is undefined or blank Return Value character(len=:), allocatable the returned value public function get_os_type () result(r) Determine the OS type Read more… Arguments None Return Value integer public function os_is_unix (os) Compare the output of get_os_type or the optional\npassed INTEGER value to the value for OS_WINDOWS\nand return .TRUE. if they match and .FALSE. otherwise Arguments Type Intent Optional Attributes Name integer, intent(in), optional :: os Return Value logical public function separator () result(sep) sample usage Read more… Arguments None Return Value character(len=1) ifort_bug*!character(len=1),save :: sep_cache=’ ‘ public function set_env (name, value, overwrite) Set an environment variable for the current environment using the C standard library Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Variable name character(len=*), intent(in) :: value Variable value logical, intent(in), optional :: overwrite Should a former value be overwritten? default = .true. Return Value logical","tags":"","loc":"module/fpm_environment.html"},{"title":"fpm_backend_console – Fortran-lang/fpm","text":"Build Backend Console This module provides a lightweight implementation for printing to the console\n and updating previously-printed console lines. It used by [[fpm_backend_output]] for pretty-printing build status and progress. @note Note\n The implementation for updating previous lines relies on no other output\n going to stdout / stderr except through the console_t object provided. @note Note\n All write statements to stdout are enclosed within OpenMP critical regions Uses iso_fortran_env Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: COLOR_GREEN = ESC//\"[32m\" Escape code for green foreground color character(len=*), public, parameter :: COLOR_RED = ESC//\"[31m\" Escape code for red foreground color character(len=*), public, parameter :: COLOR_RESET = ESC//\"[0m\" Escape code to reset foreground color character(len=*), public, parameter :: COLOR_YELLOW = ESC//\"[93m\" Escape code for yellow foreground color character(len=*), public, parameter :: LINE_RESET = ESC//\"[2K\"//ESC//\"[1G\" Escape code for erasing current line Derived Types type, public :: console_t Console object Components Type Visibility Attributes Name Initial integer, public :: n_line = 1 Number of lines printed Type-Bound Procedures procedure, public :: update_line => console_update_line ../../ Update a previously-written console line procedure, public :: write_line => console_write_line ../../ Write a single line to the console","tags":"","loc":"module/fpm_backend_console.html"},{"title":"fpm_manifest_fortran – Fortran-lang/fpm","text":"Uses fpm_toml fpm_error Derived Types type, public, extends( serializable_t ) :: fortran_config_t Configuration data for Fortran Components Type Visibility Attributes Name Initial logical, public :: implicit_external = .false. Enable implicit external interfaces logical, public :: implicit_typing = .false. Enable default implicit typing character(len=:), public, allocatable :: source_form Form to use for all Fortran sources Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => fortran_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_fortran_config (self, table, error) Construct a new build configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( fortran_config_t ), intent(out) :: self Instance of the fortran configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_fortran.html"},{"title":"fpm_toml – Fortran-lang/fpm","text":"Interface to TOML processing library This module acts as a proxy to the toml-f public Fortran API and allows\n to selectively expose components from the library to fpm .\n The interaction with toml-f data types outside of this module should be\n limited to tables, arrays and key-lists, most of the necessary interactions\n are implemented in the building interface with the get_value and set_value procedures. This module allows to implement features necessary for fpm , which are\n not yet available in upstream toml-f . For more details on the library used see the TOML-Fortran developer pages. Uses jonquil tomlf_de_parser tomlf fpm_strings iso_fortran_env fpm_error Interfaces public interface add_table add_table: fpm interface private subroutine add_table_fpm(table, key, ptr, error, whereAt) Function wrapper to add a toml table and return an fpm error Nullify pointer Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key Table key type(toml_table), intent(out), pointer :: ptr The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description public interface get_value get_value: fpm interface private subroutine get_logical(table, key, var, error, whereAt) Function wrapper to get a logical variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key logical, intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine get_integer(table, key, var, error, whereAt) Function wrapper to get a default integer variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer, intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine get_integer_64(table, key, var, error, whereAt) Function wrapper to get a integer(int64) variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer(kind=int64), intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description public interface set_string private subroutine set_character(table, key, var, error, whereAt) Function wrapper to set a character(len=:), allocatable variable to a toml table Check the key is not empty Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key List of keys to check. character(len=*), intent(in), optional :: var The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_string_type(table, key, var, error, whereAt) Function wrapper to set a character(len=:), allocatable variable to a toml table Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key List of keys to check. type( string_t ), intent(in) :: var The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description public interface set_value set_value: fpm interface private subroutine set_logical(table, key, var, error, whereAt) Function wrapper to set a logical variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key logical, intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_integer(table, key, var, error, whereAt) Function wrapper to set a default integer variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer, intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_integer_64(table, key, var, error, whereAt) Function wrapper to set a default integer variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer(kind=int64), intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description Derived Types type, public, abstract :: serializable_t An abstract interface for any fpm class that should be fully serializable to/from TOML/JSON Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure(to_toml), public, deferred :: dump_to_toml ../../ Dump to TOML table, unit, file generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure(from_toml), public, deferred :: load_from_toml ../../ Load from TOML table, unit, file generic, public :: operator(==) => serializable_is_same procedure(is_equal), public, deferred :: serializable_is_same ../../ Serializable entities need a way to check that they’re equal procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public function name_is_json (filename) Choose between JSON or TOML based on a file name Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value logical Subroutines public subroutine check_keys (table, valid_keys, error) Check if table contains only keys that are part of the list. If a key is\nfound that is not part of the list, an error is allocated. Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: valid_keys (:) List of keys to check. type( error_t ), intent(out), allocatable :: error Error handling public subroutine get_list (table, key, list, error) Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key Key to read from type( string_t ), intent(out), allocatable :: list (:) List of strings to read type( error_t ), intent(out), allocatable :: error Error handling public subroutine read_package_file (table, manifest, error) Process the configuration file to a TOML data structure Arguments Type Intent Optional Attributes Name type(toml_table), intent(out), allocatable :: table TOML data structure character(len=*), intent(in) :: manifest Name of the package configuration file type( error_t ), intent(out), allocatable :: error Error status of the operation public subroutine set_list (table, key, list, error) Set no key if array is not present Read more… Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the toml table character(len=*), intent(in) :: key Key to save to type( string_t ), intent(in), allocatable :: list (:) Instance of the string array type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_toml.html"},{"title":"fpm_cmd_install – Fortran-lang/fpm","text":"Uses fpm_installer fpm_manifest fpm_model fpm_filesystem fpm_backend fpm_strings fpm_command_line iso_fortran_env fpm_targets fpm_error fpm Subroutines public subroutine cmd_install (settings) Entry point for the fpm-install subcommand Arguments Type Intent Optional Attributes Name type( fpm_install_settings ), intent(inout) :: settings Representation of the command line settings","tags":"","loc":"module/fpm_cmd_install.html"},{"title":"fpm_installer – Fortran-lang/fpm","text":"Implementation of an installer object. The installer provides a way to install objects to their respective directories\nin the installation prefix, a generic install command allows to install\nto any directory within the prefix. Uses fpm_filesystem fpm_environment fpm_error iso_fortran_env Derived Types type, public :: installer_t Declaration of the installer type Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: bindir Binary dir relative to the installation prefix character(len=:), public, allocatable :: copy Command to copy objects into the installation prefix character(len=:), public, allocatable :: includedir Include directory relative to the installation prefix character(len=:), public, allocatable :: libdir Library directory relative to the installation prefix character(len=:), public, allocatable :: move Command to move objects into the installation prefix integer, public :: os Cached operating system character(len=:), public, allocatable :: prefix Path to installation directory integer, public :: unit = output_unit Output unit for informative printout integer, public :: verbosity = 1 Verbosity of the installer Type-Bound Procedures procedure, public :: install ../../ Install a generic file into a subdirectory in the installation prefix procedure, public :: install_executable ../../ Install an executable in its correct subdirectory procedure, public :: install_header ../../ Install a header/module in its correct subdirectory procedure, public :: install_library ../../ Install a library in its correct subdirectory procedure, public :: make_dir ../../ Create a new directory in the prefix, type-bound for unit testing purposes procedure, public :: run ../../ Run an installation command, type-bound for unit testing purposes Subroutines public subroutine new_installer (self, prefix, bindir, libdir, includedir, verbosity, copy, move) Create a new instance of an installer Arguments Type Intent Optional Attributes Name type( installer_t ), intent(out) :: self Instance of the installer character(len=*), intent(in), optional :: prefix Path to installation directory character(len=*), intent(in), optional :: bindir Binary dir relative to the installation prefix character(len=*), intent(in), optional :: libdir Library directory relative to the installation prefix character(len=*), intent(in), optional :: includedir Include directory relative to the installation prefix integer, intent(in), optional :: verbosity Verbosity of the installer character(len=*), intent(in), optional :: copy Copy command character(len=*), intent(in), optional :: move Move command","tags":"","loc":"module/fpm_installer.html"},{"title":"fpm_strings – Fortran-lang/fpm","text":"This module defines general procedures for string operations for both CHARACTER and\n TYPE(STRING_T) variables general routines for performing string operations Types TYPE(STRING_T) define a type to contain strings of variable length Type Conversions f_string return Fortran CHARACTER variable when given a C-like array of\n single characters terminated with a C_NULL_CHAR CHARACTER str Converts INTEGER or LOGICAL to CHARACTER string Case lower Changes a string to lowercase over optional specified column range Parsing and joining split parse string on delimiter characters and store tokens into an allocatable array split_first_last Computes the first and last indices of tokens in input string, delimited by the characters in set,\n and stores them into first and last output arrays. string_cat Concatenate an array of type(string_t) into a single CHARACTER variable join append an array of CHARACTER variables into a single CHARACTER variable Testing str_ends_with test if a CHARACTER string or array ends with a specified suffix string_array_contains Check if array of TYPE(STRING_T) matches a particular CHARACTER string OPERATOR(.IN.) Check if array of TYPE(STRING_T) matches a particular CHARACTER string glob function compares text strings, one of which can have wildcards (‘*’ or ‘?’). is_fortran_name determine whether a string is an acceptable Fortran entity name to_fortran_name replace allowed special but unusuable characters in names with underscore Whitespace notabs subroutine to expand tab characters assuming a tab space every eight characters dilate function to expand tab characters assuming a tab space every eight characters len_trim Determine total trimmed length of STRING_T array Miscellaneous fnv_1a Hash a CHARACTER(*) string of default kind or a TYPE(STRING_T) array replace Returns string with characters in charset replaced with target_char. resize increase the size of a TYPE(STRING_T) array by N elements Module naming License: Public Domain\n Changes a string to upprtcase over optional specified column range\n Author: Milan Curcic\n Computes the first and last indices of tokens in input string, delimited\n by the characters in set, and stores them into first and last output\n arrays.\n Author: Milan Curcic\n If back is absent, computes the leftmost token delimiter in string whose\n position is > pos. If back is present and true, computes the rightmost\n token delimiter in string whose position is < pos. The result is stored\n in pos. Uses iso_c_binding iso_fortran_env Interfaces public interface fnv_1a private pure function fnv_1a_char(input, seed) result(hash) Hash a character(*) string of default kind Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: input integer(kind=int64), intent(in), optional :: seed Return Value integer(kind=int64) private pure function fnv_1a_string_t(input, seed) result(hash) Hash a string_t array of default kind Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: input (:) integer(kind=int64), intent(in), optional :: seed Return Value integer(kind=int64) public interface len_trim private elemental function string_len_trim(string) result(n) Determine total trimmed length of string_t array Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: string Return Value integer private pure function strings_len_trim(strings) result(n) Determine total trimmed length of string_t array Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: strings (:) Return Value integer public interface operator(.in.) public function string_array_contains (search_string, array) Check if array of TYPE(STRING_T) matches a particular CHARACTER string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: search_string type( string_t ), intent(in) :: array (:) Return Value logical public interface operator(==) private pure function string_is_same(this, that) Check that two string objects are exactly identical Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: this two strings to be compared type( string_t ), intent(in) :: that two strings to be compared Return Value logical private pure function string_arrays_same(this, that) Check that two allocatable string object arrays are exactly identical Arguments Type Intent Optional Attributes Name type( string_t ), intent(in), allocatable :: this (:) two string arrays to be compared type( string_t ), intent(in), allocatable :: that (:) two string arrays to be compared Return Value logical public interface resize private subroutine resize_string(list, n) increase the size of a TYPE(STRING_T) array by N elements Arguments Type Intent Optional Attributes Name type( string_t ), intent(inout), allocatable :: list (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size public interface str private pure function str_int(i) result(s) Converts integer “i” to string Arguments Type Intent Optional Attributes Name integer, intent(in) :: i Return Value character(len=str_int_len) private pure function str_int64(i) result(s) Converts integer “i” to string Arguments Type Intent Optional Attributes Name integer(kind=int64), intent(in) :: i Return Value character(len=str_int64_len) private pure function str_logical(l) result(s) Converts logical “l” to string Arguments Type Intent Optional Attributes Name logical, intent(in) :: l Return Value character(len=str_logical_len) public interface str_ends_with private pure function str_ends_with_str(s, e) result(r) test if a CHARACTER string ends with a specified suffix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e Return Value logical private pure function str_ends_with_any(s, e) result(r) test if a CHARACTER string ends with any of an array of suffixs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e (:) Return Value logical private pure function str_ends_with_any_string(s, e) result(r) Test if a CHARACTER string ends with any of an array of string suffixs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s type( string_t ), intent(in) :: e (:) Return Value logical public interface string_t private function new_string_t(s) result(string) Helper function to generate a new string_t instance\n (Required due to the allocatable component) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s Return Value type( string_t ) Derived Types type, public :: string_t Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: s Constructor private\n\n \n function new_string_t (s) Helper function to generate a new string_t instance\n (Required due to the allocatable component) Functions public function dilate (instr) result(outstr) Author John S. Urban License Public Domain Sample program: Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: instr Return Value character(len=:), allocatable public function f_string (c_string) return Fortran character variable when given a C-like array of\nsingle characters terminated with a C_NULL_CHAR character Arguments Type Intent Optional Attributes Name character(len=1), intent(in) :: c_string (:) Return Value character(len=:), allocatable public function glob (tame, wild) Author John S. Urban License Public Domain glob(3f) compares given STRING for match to PATTERN which may\n contain wildcard characters. Read more… Arguments Type Intent Optional Attributes Name character(len=*) :: tame A string without wildcards to compare to the globbing expression character(len=*) :: wild A (potentially) corresponding string with wildcards Return Value logical result of test public function has_valid_custom_prefix (module_name, custom_prefix) result(valid) Check that a module name is prefixed with a custom prefix:\n1) It must be a valid FORTRAN name subset (<=63 chars, begin with letter, only alphanumeric allowed)\n2) It must begin with the prefix\n3) If longer, package name must be followed by default separator (“_”) plus at least one char Read more… Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: custom_prefix Return Value logical public function has_valid_standard_prefix (module_name, package_name) result(valid) Check that a module name is prefixed with the default package prefix:\n1) It must be a valid FORTRAN name (<=63 chars, begin with letter, “_” is only allowed non-alphanumeric)\n2) It must begin with the package name\n3) If longer, package name must be followed by default separator plus at least one char Read more… Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: package_name Return Value logical public elemental function is_fortran_name (line) result(lout) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: line Return Value logical public function is_valid_module_name (module_name, package_name, custom_prefix, enforce_module_names) result(valid) Check that a module name fits the current naming rules:\n1) It must be a valid FORTRAN name (<=63 chars, begin with letter, “_” is only allowed non-alphanumeric)\n2) It must begin with the package name\n3) If longer, package name must be followed by default separator plus at least one char Read more… Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: package_name type( string_t ), intent(in) :: custom_prefix logical, intent(in) :: enforce_module_names Return Value logical public function is_valid_module_prefix (module_prefix) result(valid) Check that a custom module prefix fits the current naming rules:\n1) Only alphanumeric characters (no spaces, dashes, underscores or other characters)\n2) Does not begin with a number (Fortran-compatible syntax) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_prefix Return Value logical public pure function join (str, sep, trm, left, right, start, end) result(string) Author John S. Urban License Public Domain JOIN(3f) appends the elements of a CHARACTER array into a single\n CHARACTER variable, with elements 1 to N joined from left to right.\n By default each element is trimmed of trailing spaces and the\n default separator is a null string. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str (:) character(len=*), intent(in), optional :: sep logical, intent(in), optional :: trm character(len=*), intent(in), optional :: left character(len=*), intent(in), optional :: right character(len=*), intent(in), optional :: start character(len=*), intent(in), optional :: end Return Value character(len=:), allocatable public pure elemental function lower (str, begin, end) result(string) Author John S. Urban License Public Domain Changes a string to lowercase over optional specified column range Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str integer, intent(in), optional :: begin integer, intent(in), optional :: end Return Value character(len=len(str)) public function module_prefix_template (project_name, custom_prefix) result(prefix) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: project_name type( string_t ), intent(in) :: custom_prefix Return Value type( string_t ) public function module_prefix_type (project_name, custom_prefix) result(ptype) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: project_name type( string_t ), intent(in) :: custom_prefix Return Value type( string_t ) public pure function replace (string, charset, target_char) result(res) Returns string with characters in charset replaced with target_char. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string character(len=1), intent(in) :: charset (:) character(len=1), intent(in) :: target_char Return Value character(len=len(string)) public pure function str_begins_with_str (s, e, case_sensitive) result(r) test if a CHARACTER string begins with a specified prefix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e logical, intent(in), optional :: case_sensitive Return Value logical public function string_array_contains (search_string, array) Check if array of TYPE(STRING_T) matches a particular CHARACTER string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: search_string type( string_t ), intent(in) :: array (:) Return Value logical public function string_cat (strings, delim) result(cat) Concatenate an array of type(string_t) into\n a single CHARACTER variable Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: strings (:) character(len=*), intent(in), optional :: delim Return Value character(len=:), allocatable public pure function to_fortran_name (string) result(res) Returns string with special characters replaced with an underscore.\nFor now, only a hyphen is treated as a special character, but this can be\nexpanded to other characters if needed. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string Return Value character(len=len(string)) public pure elemental function upper (str, begin, end) result(string) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str integer, intent(in), optional :: begin integer, intent(in), optional :: end Return Value character(len=len(str)) Subroutines public impure elemental subroutine notabs (instr, outstr, ilen) Author John S. Urban License Public Domain notabs(3f) - [fpm_strings:NONALPHA] expand tab characters\n (LICENSE:PD) Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: instr character(len=*), intent(out) :: outstr integer, intent(out) :: ilen public subroutine remove_characters_in_set (string, set, replace_with) Arguments Type Intent Optional Attributes Name character(len=:), intent(inout), allocatable :: string character(len=*), intent(in) :: set character(len=1), intent(in), optional :: replace_with public subroutine remove_newline_characters (string) Arguments Type Intent Optional Attributes Name type( string_t ), intent(inout) :: string public subroutine split (input_line, array, delimiters, order, nulls) Author John S. Urban License Public Domain parse string on delimiter characters and store tokens into an allocatable array\ngiven a line of structure ” par1 par2 par3 … parn ” store each par(n) into a separate variable in array. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: input_line input string to tokenize character(len=:), intent(out), allocatable :: array (:) output array of tokens character(len=*), intent(in), optional :: delimiters list of delimiter characters character(len=*), intent(in), optional :: order order of output array sequential|[reverse|right] character(len=*), intent(in), optional :: nulls return strings composed of delimiters or not ignore|return|ignoreend public pure subroutine split_first_last (string, set, first, last) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string character(len=*), intent(in) :: set integer, intent(out), allocatable :: first (:) integer, intent(out), allocatable :: last (:)","tags":"","loc":"module/fpm_strings.html"},{"title":"fpm_pkg_config – Fortran-lang/fpm","text":"The fpm interface to pkg-config This module contains wrapper functions to interface with a pkg-config installation. Uses fpm_environment fpm_strings shlex_module fpm_error fpm_filesystem Functions public function assert_pkg_config () Check whether pkg-config is available on the local system Arguments None Return Value logical public function pkgcfg_get_build_flags (name, allow_system, error) result(flags) Get build flags (option to include flags from system directories, that \ngfortran does not look into by default) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Package name logical, intent(in) :: allow_system Should pkg-config look in system paths? This is necessary for gfortran \nthat doesn’t otherwise look into them type( error_t ), intent(out), allocatable :: error Error flag Return Value type( string_t ), allocatable, (:) List of compile flags public function pkgcfg_get_libs (package, error) result(libraries) Get package libraries from pkg-config Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: package Package name type( error_t ), intent(out), allocatable :: error Error handler Return Value type( string_t ), allocatable, (:) A list of libraries public function pkgcfg_get_version (package, error) result(screen) Get package version from pkg-config Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: package Package name type( error_t ), intent(out), allocatable :: error Error handler Return Value type( string_t ) public function pkgcfg_has_package (name) result(success) Check if pkgcfg has package Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Package name Return Value logical public function pkgcfg_list_all (error, descriptions) result(modules) Return whole list of available pkg-cfg packages Read more… Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Error handler type( string_t ), intent(out), optional, allocatable :: descriptions (:) An optional list of package descriptions Return Value type( string_t ), allocatable, (:) A list of all available packages Subroutines public subroutine run_wrapper (wrapper, args, verbose, exitcode, cmd_success, screen_output) Simple call to execute_command_line involving one mpi* wrapper Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: wrapper type( string_t ), intent(in), optional :: args (:) logical, intent(in), optional :: verbose integer, intent(out), optional :: exitcode logical, intent(out), optional :: cmd_success type( string_t ), intent(out), optional :: screen_output","tags":"","loc":"module/fpm_pkg_config.html"},{"title":"fpm_meta – Fortran-lang/fpm","text":"The fpm meta-package model This is a wrapper data type that encapsulate all pre-processing information\n (compiler flags, linker libraries, etc.) required to correctly enable a package\n to use a core library. Available core libraries OpenMP MPI HDF5 fortran-lang stdlib fortran-lang minpack @note Note\n Core libraries are enabled in the [build] section of the fpm.toml manifest Uses fpm_pkg_config fpm_environment fpm_os fpm_git fpm_manifest_dependency fpm_manifest fpm_filesystem fpm_strings fpm_versioning fpm_command_line fpm_compiler shlex_module iso_fortran_env regex_module fpm_error fpm_model Interfaces public interface resolve_metapackages private subroutine resolve_metapackage_model(model, package, settings, error) Resolve all metapackages into the package config Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(inout) :: model type( package_config_t ), intent(inout) :: package class( fpm_build_settings ), intent(inout) :: settings type( error_t ), intent(out), allocatable :: error Derived Types type, public :: metapackage_t Type for describing a source file Components Type Visibility Attributes Name Initial type( string_t ), public :: cflags type( string_t ), public :: cxxflags type( dependency_config_t ), public, allocatable :: dependency (:) List of Development dependency meta data.\nMetapackage dependencies are never exported from the model type( string_t ), public, allocatable :: external_modules (:) type( string_t ), public :: fflags type( string_t ), public :: flags List of compiler flags and options to be added type( fortran_features_t ), public, allocatable :: fortran Special fortran features logical, public :: has_build_flags = .false. logical, public :: has_c_flags = .false. logical, public :: has_cxx_flags = .false. logical, public :: has_dependencies = .false. logical, public :: has_external_modules = .false. logical, public :: has_fortran_flags = .false. logical, public :: has_include_dirs = .false. logical, public :: has_link_flags = .false. logical, public :: has_link_libraries = .false. logical, public :: has_run_command = .false. type( string_t ), public, allocatable :: incl_dirs (:) type( string_t ), public :: link_flags type( string_t ), public, allocatable :: link_libs (:) type( string_t ), public :: run_command type( version_t ), public, allocatable :: version Package version (if supported) Type-Bound Procedures procedure, public :: destroy ../../ Clean metapackage structure procedure, public :: new => init_from_name ../../ Initialize the metapackage structure from its given name generic, public :: resolve => resolve_cmd, resolve_model, resolve_package_config Functions public pure function MPI_TYPE_NAME (mpilib) result(name) Return a name for the MPI library Arguments Type Intent Optional Attributes Name integer, intent(in) :: mpilib Return Value character(len=:), allocatable","tags":"","loc":"module/fpm_meta.html"},{"title":"fpm_backend – Fortran-lang/fpm","text":"Build backend Uses a list of [[build_target_ptr]] and a valid [[fpm_model]] instance\n to schedule and execute the compilation and linking of package targets. The package build process ( [[build_package]] ) comprises three steps: Target sorting: topological sort of the target dependency graph ( [[sort_target]] ) Target scheduling: group targets into schedule regions based on the sorting ( [[schedule_targets]] ) Target building: generate targets by compilation or linking @note Note\n If compiled with OpenMP, targets will be build in parallel where possible. Incremental compilation The backend process supports incremental compilation whereby targets are not\n re-compiled if their corresponding dependencies have not been modified. Source-based targets ( i.e. objects) are not re-compiled if the corresponding source\n file is unmodified AND all of the target dependencies are not marked for re-compilation Link targets ( i.e. executables and libraries) are not re-compiled if the\n target output file already exists AND all of the target dependencies are not marked for\n re-compilation Source file modification is determined by a file digest (hash) which is calculated during\n the source parsing phase ( fpm_source_parsing ) and cached to disk after a target is\n successfully generated. Uses fpm_backend_output fpm_filesystem fpm_strings iso_fortran_env fpm_targets fpm_error fpm_model Subroutines public subroutine build_package (targets, model, verbose) Top-level routine to build package described by model Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout) :: targets (:) type( fpm_model_t ), intent(in) :: model logical, intent(in) :: verbose public subroutine schedule_targets (queue, schedule_ptr, targets) Construct a build schedule from the sorted targets. Read more… Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(out), allocatable :: queue (:) integer, allocatable :: schedule_ptr (:) type( build_target_ptr ), intent(in) :: targets (:) public recursive subroutine sort_target (target) Topologically sort a target for scheduling by\n recursing over its dependencies. Read more… Arguments Type Intent Optional Attributes Name type( build_target_t ), intent(inout), target :: target","tags":"","loc":"module/fpm_backend.html"},{"title":"fpm_git – Fortran-lang/fpm","text":"Implementation for interacting with git repositories. Uses fpm_toml fpm_error fpm_filesystem Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: compressed_package_name = 'compressed_package' Name of the compressed package that is generated temporarily. type( enum_descriptor ), public, parameter :: git_descriptor = enum_descriptor() Actual enumerator for descriptors character(len=*), public, parameter :: out_fmt = '(\"#\", *(1x, g0))' Common output format for writing to the command line Derived Types type, public :: enum_descriptor Possible git target Components Type Visibility Attributes Name Initial integer, public :: branch = 201 Branch in git repository integer, public :: default = 200 Default target integer, public :: error = -999 Invalid descriptor integer, public :: revision = 203 Commit hash integer, public :: tag = 202 Tag in git repository type, public, extends( serializable_t ) :: git_target_t Description of an git target Components Type Visibility Attributes Name Initial integer, public :: descriptor = git_descriptor%default Kind of the git target character(len=:), public, allocatable :: object Additional descriptor of the git object character(len=:), public, allocatable :: url Target URL of the git repository Type-Bound Procedures procedure, public :: checkout ../../ Fetch and checkout in local directory generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Show information on instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => git_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public pure function descriptor_name (descriptor) result(name) Code git descriptor to a string Arguments Type Intent Optional Attributes Name integer, intent(in) :: descriptor Return Value character(len=:), allocatable public function git_is_same (this, that) Check that two git targets are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical public function git_matches_manifest (cached, manifest, verbosity, iunit) Check that a cached dependency matches a manifest request Read more… Arguments Type Intent Optional Attributes Name type( git_target_t ), intent(in) :: cached Two input git targets type( git_target_t ), intent(in) :: manifest Two input git targets integer, intent(in) :: verbosity integer, intent(in) :: iunit Return Value logical public function git_target_branch (url, branch) result(self) Target a branch in the git repository Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: branch Name of the branch of interest Return Value type( git_target_t ) New git target public function git_target_default (url) result(self) Default target Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository Return Value type( git_target_t ) New git target public function git_target_revision (url, sha1) result(self) Target a specific git revision Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: sha1 Commit hash of interest Return Value type( git_target_t ) New git target public function git_target_tag (url, tag) result(self) Target a git tag Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: tag Tag name of interest Return Value type( git_target_t ) New git target public pure function parse_descriptor (name) Parse git descriptor identifier from a string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Return Value integer Subroutines public subroutine checkout (self, local_path, error) Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target character(len=*), intent(in) :: local_path Local path to checkout in type( error_t ), intent(out), allocatable :: error Error public subroutine dump_to_toml (self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine git_archive (source, destination, ref, additional_files, verbose, error) Archive a folder using git archive . Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: source Directory to archive. character(len=*), intent(in) :: destination Destination of the archive. character(len=*), intent(in) :: ref (Symbolic) Reference to be archived. character(len=*), intent(in), optional :: additional_files (:) (Optional) list of additional untracked files to be added to the archive. logical, intent(in) :: verbose Print additional information if true. type( error_t ), intent(out), allocatable :: error Error handling. public subroutine git_revision (local_path, object, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: local_path Local path to checkout in character(len=:), intent(out), allocatable :: object Git object reference type( error_t ), intent(out), allocatable :: error Error public subroutine info (self, unit, verbosity) Show information on git target Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout public subroutine load_from_toml (self, table, error) Read dependency from toml table (no checks made at this stage) Read more… Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_git.html"},{"title":"fpm_manifest_dependency – Fortran-lang/fpm","text":"Implementation of the meta data for dependencies. A dependency table can currently have the following fields [dependencies] \"dep1\" = { git = \"url\" } \"dep2\" = { git = \"url\" , branch = \"name\" } \"dep3\" = { git = \"url\" , tag = \"name\" } \"dep4\" = { git = \"url\" , rev = \"sha1\" } \"dep0\" = { path = \"path\" } To reduce the amount of boilerplate code this module provides two constructors\n for dependency types, one basic for an actual dependency (inline) table\n and another to collect all dependency objects from a dependencies table,\n which is handling the allocation of the objects and is forwarding the\n individual dependency tables to their respective constructors.\n The usual entry point should be the constructor for the super table. This objects contains a target to retrieve required fpm projects to\n build the target declaring the dependency.\n Resolving a dependency will result in obtaining a new package configuration\n data for the respective project. Uses fpm_environment fpm_toml fpm_manifest_preprocess fpm_git fpm_versioning fpm_strings fpm_manifest_metapackages fpm_error fpm_filesystem Interfaces public interface resize private pure subroutine resize_dependency_config(var, n) Reallocate a list of dependencies Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(inout), allocatable :: var (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size Derived Types type, public, extends( serializable_t ) :: dependency_config_t Configuration meta data for a dependency Components Type Visibility Attributes Name Initial type( git_target_t ), public, allocatable :: git Git descriptor character(len=:), public, allocatable :: name Name of the dependency character(len=:), public, allocatable :: namespace Namespace which the dependency belongs to.\nEnables multiple dependencies with the same name.\nRequired for dependencies that are obtained via the official registry. character(len=:), public, allocatable :: path Local target type( preprocess_config_t ), public, allocatable :: preprocess (:) Requested macros for the dependency type( version_t ), public, allocatable :: requested_version The requested version of the dependency.\nThe latest version is used if not specified. Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => dependency_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public function manifest_has_changed (cached, manifest, verbosity, iunit) result(has_changed) Check if two dependency configurations are different Read more… Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(in) :: cached Two instances of the dependency configuration class( dependency_config_t ), intent(in) :: manifest Two instances of the dependency configuration integer, intent(in) :: verbosity Log verbosity integer, intent(in) :: iunit Log verbosity Return Value logical Subroutines public elemental subroutine dependency_destroy (self) Clean memory Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(inout) :: self public subroutine new_dependencies (deps, table, root, meta, error) Construct new dependency array from a TOML data structure Read more… Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(out), allocatable :: deps (:) Instance of the dependency configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( metapackage_config_t ), intent(out), optional :: meta (optional) metapackages type( error_t ), intent(out), allocatable :: error Error handling public subroutine new_dependency (self, table, root, error) Construct a new dependency configuration from a TOML data structure Read more… Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(out) :: self Instance of the dependency configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_dependency.html"},{"title":"fpm_filesystem – Fortran-lang/fpm","text":"This module contains general routines for interacting with the file system Directories are not files for the Intel compilers. If so, also use this compiler-dependent extension Uses fpm_environment iso_c_binding fpm_strings iso_fortran_env fpm_error Functions public function basename (path, suffix) result(base) Extract filename from path with/without suffix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path logical, intent(in), optional :: suffix Return Value character(len=:), allocatable public function canon_path (path) Canonicalize path for comparison\n* Handles path string redundancies\n* Does not test existence of path Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function dirname (path) result(dir) Extract dirname from path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function exists (filename) result(r) test if pathname already exists Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value logical public function get_dos_path (path, error) Ensure a windows path is converted to an 8.3 DOS path if it contains spaces\nNo need to convert if there are no spaces Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path type( error_t ), intent(out), allocatable :: error Return Value character(len=:), allocatable public function get_local_prefix (os) result(prefix) Determine the path prefix to the local folder. Used for installation, registry etc. Arguments Type Intent Optional Attributes Name integer, intent(in), optional :: os Platform identifier Return Value character(len=:), allocatable Installation prefix public function get_temp_filename () result(tempfile) Get a unused temporary filename\n Calls posix ‘tempnam’ - not recommended, but\n we have no security concerns for this application\n and use here is temporary.\nWorks with MinGW Arguments None Return Value character(len=:), allocatable public function is_absolute_path (path, is_unix) Returns .true. if provided path is absolute. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path logical, intent(in), optional :: is_unix Return Value logical public function is_dir (dir) test if a name matches an existing directory path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir Return Value logical public function is_hidden_file (file_basename) result(r) test if a file is hidden Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file_basename Return Value logical public function join_path (a1, a2, a3, a4, a5) result(path) Construct path by joining strings with os file separator Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: a1 character(len=*), intent(in) :: a2 character(len=*), intent(in), optional :: a3 character(len=*), intent(in), optional :: a4 character(len=*), intent(in), optional :: a5 Return Value character(len=:), allocatable public function number_of_rows (s) result(nrows) Determine number or rows in a file given a LUN Arguments Type Intent Optional Attributes Name integer, intent(in) :: s Return Value integer public function parent_dir (path) result(dir) Extract dirname from path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function read_lines (filename) result(lines) read lines into an array of TYPE(STRING_T) variables Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value type( string_t ), allocatable, (:) public function read_lines_expanded (filename) result(lines) read lines into an array of TYPE(STRING_T) variables expanding tabs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value type( string_t ), allocatable, (:) public function unix_path (path) result(nixpath) Replace file system separators for unix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function which (command) result(pathname) Author John S. Urban License Public Domain function which(command) result(pathname) Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: command Return Value character(len=:), allocatable public function windows_path (path) result(winpath) Replace file system separators for windows Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Subroutines public subroutine delete_file (file) delete a file by filename Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file public subroutine execute_and_read_output (cmd, output, error, verbose) Execute command line and return output as a string. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: cmd Command to execute. character(len=:), intent(out), allocatable :: output Command line output. type( error_t ), intent(out), allocatable :: error Error to handle. logical, intent(in), optional :: verbose Print additional information if true. public subroutine fileclose (lun, ier) simple close of a LUN. On error show message and stop (by default) Arguments Type Intent Optional Attributes Name integer, intent(in) :: lun integer, intent(out), optional :: ier public subroutine fileopen (filename, lun, ier) procedure to open filename as a sequential “text” file Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename integer, intent(out) :: lun integer, intent(out), optional :: ier public subroutine filewrite (filename, filedata) procedure to write filedata to file filename Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename character(len=*), intent(in) :: filedata (:) public subroutine get_home (home, error) Get the HOME directory on Unix and the %USERPROFILE% directory on Windows. Arguments Type Intent Optional Attributes Name character(len=:), intent(out), allocatable :: home type( error_t ), intent(out), allocatable :: error public subroutine getline (unit, line, iostat, iomsg) Author fpm(1) contributors License MIT subroutine getline(unit,line,iostat,iomsg) Read more… Arguments Type Intent Optional Attributes Name integer, intent(in) :: unit Formatted IO unit character(len=:), intent(out), allocatable :: line Line to read integer, intent(out) :: iostat Status of operation character(len=:), optional, allocatable :: iomsg Error message public recursive subroutine list_files (dir, files, recurse) Get file & directory names in directory dir using iso_c_binding. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir type( string_t ), intent(out), allocatable :: files (:) logical, intent(in), optional :: recurse public subroutine mkdir (dir, echo) Create a directory. Create subdirectories as needed Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir logical, intent(in), optional :: echo public subroutine os_delete_dir (is_unix, dir, echo) Delete directory using system OS remove directory commands Arguments Type Intent Optional Attributes Name logical, intent(in) :: is_unix character(len=*), intent(in) :: dir logical, intent(in), optional :: echo public subroutine run (cmd, echo, exitstat, verbose, redirect) Author fpm(1) contributors License MIT Execute the specified system command. Optionally Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: cmd logical, intent(in), optional :: echo integer, intent(out), optional :: exitstat logical, intent(in), optional :: verbose character(len=*), intent(in), optional :: redirect public subroutine warnwrite (fname, data) write trimmed character data to a file if it does not exist Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: fname character(len=*), intent(in) :: data (:)","tags":"","loc":"module/fpm_filesystem.html"},{"title":"fpm_downloader – Fortran-lang/fpm","text":"Uses jonquil fpm_versioning fpm_strings fpm_error fpm_filesystem Derived Types type, public :: downloader_t This type could be entirely avoided but it is quite practical because it can be mocked for testing. Type-Bound Procedures procedure, public, nopass :: get_file procedure, public, nopass :: get_pkg_data procedure, public, nopass :: unpack procedure, public, nopass :: upload_form","tags":"","loc":"module/fpm_downloader.html"},{"title":"fpm_os – Fortran-lang/fpm","text":"Uses iso_c_binding fpm_environment fpm_error fpm_filesystem Subroutines public subroutine change_directory (path, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path type( error_t ), intent(out), allocatable :: error public subroutine convert_to_absolute_path (path, error) Converts a path to an absolute, canonical path. Arguments Type Intent Optional Attributes Name character(len=:), intent(inout), allocatable :: path type( error_t ), intent(out), allocatable :: error public subroutine get_absolute_path (path, absolute_path, error) Determine the canonical, absolute path for the given path.\nExpands home folder (~) on both Unix and Windows. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path character(len=:), intent(out), allocatable :: absolute_path type( error_t ), intent(out), allocatable :: error public subroutine get_absolute_path_by_cd (path, absolute_path, error) Alternative to get_absolute_path that uses chdir / _chdir to determine the absolute path. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path character(len=:), intent(out), allocatable :: absolute_path type( error_t ), intent(out), allocatable :: error public subroutine get_current_directory (path, error) Arguments Type Intent Optional Attributes Name character(len=:), intent(out), allocatable :: path type( error_t ), intent(out), allocatable :: error","tags":"","loc":"module/fpm_os.html"},{"title":"fpm_dependency – Fortran-lang/fpm","text":"Dependency management Fetching dependencies and creating a dependency tree Dependencies on the top-level can be specified from: package%dependencies package%dev_dependencies package%executable(:)%dependencies package%test(:)%dependencies Each dependency is fetched in some way and provides a path to its package\nmanifest.\nThe package%dependencies of the dependencies are resolved recursively. To initialize the dependency tree all dependencies are recursively fetched\nand stored in a flat data structure to avoid retrieving a package twice.\nThe data structure used to store this information should describe the current\nstatus of the dependency tree. Important information are: name of the package version of the package path to the package root Additionally, for version controlled dependencies the following should be\nstored along with the package: the upstream url the current checked out revision Fetching a remote (version controlled) dependency turns it for our purpose\ninto a local path dependency which is handled by the same means. Updating dependencies For a given dependency tree all top-level dependencies can be updated.\nWe have two cases to consider, a remote dependency and a local dependency,\nagain, remote dependencies turn into local dependencies by fetching.\nTherefore we will update remote dependencies by simply refetching them. For remote dependencies we have to refetch if the revision in the manifest\nchanges or the upstream HEAD has changed (for branches and tags). Note For our purpose a tag is just a fancy branch name. Tags can be delete and\n modified afterwards, therefore they do not differ too much from branches\n from our perspective. For the latter case we only know if we actually fetch from the upstream URL. In case of local (and fetched remote) dependencies we have to read the package\nmanifest and compare its dependencies against our dependency tree, any change\nrequires updating the respective dependencies as well. Handling dependency compatibilties Currenly ignored. First come, first serve. Uses fpm_environment fpm_toml jonquil fpm_manifest_preprocess fpm_git fpm_manifest fpm_manifest_dependency fpm_strings fpm_versioning iso_fortran_env fpm_downloader fpm_settings fpm_error fpm_filesystem Interfaces public interface resize Overloaded reallocation interface private pure subroutine resize_dependency_node(var, n) Reallocate a list of dependencies Arguments Type Intent Optional Attributes Name type( dependency_node_t ), intent(inout), allocatable :: var (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size Derived Types type, public, extends( dependency_config_t ) :: dependency_node_t Dependency node in the projects dependency tree Components Type Visibility Attributes Name Initial logical, public :: cached = .false. Dependency was loaded from a cache logical, public :: done = .false. Dependency is handled type( git_target_t ), public, allocatable :: git Git descriptor character(len=:), public, allocatable :: name Name of the dependency character(len=:), public, allocatable :: namespace Namespace which the dependency belongs to.\nEnables multiple dependencies with the same name.\nRequired for dependencies that are obtained via the official registry. character(len=:), public, allocatable :: path Local target type( preprocess_config_t ), public, allocatable :: preprocess (:) Requested macros for the dependency character(len=:), public, allocatable :: proj_dir Installation prefix of this dependencies type( version_t ), public, allocatable :: requested_version The requested version of the dependency.\nThe latest version is used if not specified. character(len=:), public, allocatable :: revision Checked out revision of the version control system logical, public :: update = .false. Dependency should be updated type( version_t ), public, allocatable :: version Actual version of this dependency Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => node_dump_to_toml procedure, public :: get_from_registry ../../ Get dependency from the registry. procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => node_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: register ../../ Update dependency from project manifest. procedure, public :: serializable_is_same => dependency_node_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: dependency_tree_t Respresentation of a projects dependencies Read more… Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: cache Cache file type( dependency_node_t ), public, allocatable :: dep (:) Flattend list of all dependencies character(len=:), public, allocatable :: dep_dir Installation prefix for dependencies integer, public :: ndep = 0 Number of currently registered dependencies integer, public :: unit = output_unit Unit for IO integer, public :: verbosity = 1 Verbosity of printout Type-Bound Procedures generic, public :: add => add_project, add_project_dependencies, add_dependencies, add_dependency, add_dependency_node ../../ Overload procedure to add new dependencies to the tree generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit generic, public :: dump_cache => dump_cache_to_file, dump_cache_to_unit, dump_cache_to_toml ../../ Writing of dependency tree procedure, public :: dump_to_toml => tree_dump_to_toml generic, public :: find => find_name ../../ Find a dependency in the tree procedure, public :: finished ../../ Depedendncy resolution finished generic, public :: has => has_dependency ../../ True if entity can be found generic, public :: load => load_from_toml , load_from_file, load_from_unit generic, public :: load_cache => load_cache_from_file, load_cache_from_unit, load_cache_from_toml ../../ Reading of dependency tree procedure, public :: load_from_toml => tree_load_from_toml generic, public :: operator(==) => serializable_is_same generic, public :: resolve => resolve_dependencies, resolve_dependency ../../ Resolve dependencies procedure, public :: serializable_is_same => dependency_tree_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip generic, public :: update => update_dependency, update_tree ../../ Update dependency tree Subroutines public subroutine check_and_read_pkg_data (json, node, download_url, version, error) Arguments Type Intent Optional Attributes Name type(json_object), intent(inout) :: json class( dependency_node_t ), intent(in) :: node character(len=:), intent(out), allocatable :: download_url type( version_t ), intent(out) :: version type( error_t ), intent(out), allocatable :: error public elemental subroutine destroy_dependency_node (self) Destructor Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self public subroutine new_dependency_node (self, dependency, version, proj_dir, update) Create a new dependency node from a configuration Arguments Type Intent Optional Attributes Name type( dependency_node_t ), intent(out) :: self Instance of the dependency node type( dependency_config_t ), intent(in) :: dependency Dependency configuration data type( version_t ), intent(in), optional :: version Version of the dependency character(len=*), intent(in), optional :: proj_dir Installation prefix of the dependency logical, intent(in), optional :: update Dependency should be updated public subroutine new_dependency_tree (self, verbosity, cache) Create a new dependency tree Arguments Type Intent Optional Attributes Name type( dependency_tree_t ), intent(out) :: self Instance of the dependency tree integer, intent(in), optional :: verbosity Verbosity of printout character(len=*), intent(in), optional :: cache Name of the cache file","tags":"","loc":"module/fpm_dependency.html"},{"title":"fpm_release – Fortran-lang/fpm","text":"Release parameters Module fpm_release contains public constants storing this build’s unique version IDs Uses fpm_versioning fpm_error Functions public function fpm_version () Return the current fpm version from fpm_version_ID as a version type Arguments None Return Value type( version_t )","tags":"","loc":"module/fpm_release.html"},{"title":"fpm_manifest_preprocess – Fortran-lang/fpm","text":"Implementation of the meta data for preprocessing. A preprocess table can currently have the following fields [preprocess] [preprocess.cpp] suffixes = [ \"F90\" , \"f90\" ] directories = [ \"src/feature1\" , \"src/models\" ] macros = [] Uses fpm_strings fpm_toml fpm_error iso_fortran_env Derived Types type, public, extends( serializable_t ) :: preprocess_config_t Configuration meta data for a preprocessor Components Type Visibility Attributes Name Initial type( string_t ), public, allocatable :: directories (:) Directories to search for files to be preprocessed type( string_t ), public, allocatable :: macros (:) Macros to be defined for the preprocessor character(len=:), public, allocatable :: name Name of the preprocessor type( string_t ), public, allocatable :: suffixes (:) Suffixes of the files to be preprocessed Type-Bound Procedures procedure, public :: add_config procedure, public :: destroy ../../ Operations generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance procedure, public :: is_cpp ../../ Properties procedure, public :: is_fypp generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => preprocess_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_preprocess_config (self, table, error) Construct a new preprocess configuration from TOML data structure Arguments Type Intent Optional Attributes Name type( preprocess_config_t ), intent(out) :: self Instance of the preprocess configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure. type( error_t ), intent(out), allocatable :: error Error handling public subroutine new_preprocessors (preprocessors, table, error) Construct new preprocess array from a TOML data structure. Arguments Type Intent Optional Attributes Name type( preprocess_config_t ), intent(out), allocatable :: preprocessors (:) Instance of the preprocess configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_preprocess.html"},{"title":"fpm_cmd_publish – Fortran-lang/fpm","text":"Upload a package to the registry using the publish command. To upload a package you need to provide a token that will be linked to your username and created for a namespace.\nThe token can be obtained from the registry website. It can be used as fpm publish --token . Uses fpm_git fpm_manifest fpm_filesystem fpm_versioning fpm_strings fpm_command_line fpm fpm_downloader fpm_settings fpm_error fpm_model Subroutines public subroutine cmd_publish (settings) The publish command first builds the root package to obtain all the relevant information such as the\npackage version. It then creates a tarball of the package and uploads it to the registry.\nChecks before uploading the package. Arguments Type Intent Optional Attributes Name type( fpm_publish_settings ), intent(inout) :: settings","tags":"","loc":"module/fpm_cmd_publish.html"},{"title":"fpm_settings – Fortran-lang/fpm","text":"Manages global settings which are defined in the global config file. Uses fpm_toml fpm_environment fpm_os fpm_error fpm_filesystem Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: official_registry_base_url = 'https://fpm-registry.vercel.app' Derived Types type, public :: fpm_global_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: config_file_name Name of the global config file. The default is config.toml . character(len=:), public, allocatable :: path_to_config_folder Path to the global config file excluding the file name. type(fpm_registry_settings), public, allocatable :: registry_settings Registry configs. Type-Bound Procedures procedure, public :: full_path procedure, public :: has_custom_location procedure, public :: path_to_config_folder_or_empty Subroutines public subroutine get_global_settings (global_settings, error) Obtain global settings from the global config file. Arguments Type Intent Optional Attributes Name type( fpm_global_settings ), intent(inout) :: global_settings Global settings to be obtained. type( error_t ), intent(out), allocatable :: error Error reading config file. public subroutine get_registry_settings (table, global_settings, error) Read registry settings from the global config file. Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout), target :: table The [registry] subtable from the global config file. type( fpm_global_settings ), intent(inout) :: global_settings The global settings which can be filled with the registry settings. type( error_t ), intent(out), allocatable :: error Error handling.","tags":"","loc":"module/fpm_settings.html"},{"title":"fpm_model – Fortran-lang/fpm","text":"The fpm package model Defines the fpm model data types which encapsulate all information\n required to correctly build a package and its dependencies. The process (see [[build_model(subroutine)]] ) for generating a valid [[fpm_model]] involves\n source files discovery ( fpm_sources ) and parsing ( fpm_source_parsing ). Once a valid [[fpm_model]] has been constructed, it may be passed to [[fpm_targets:targets_from_sources]] to\n generate a list of build targets for the backend. Enumerations Source type: FPM_UNIT_* Describes the type of source file — determines build target generation The logical order of precedence for assigning unit_type is as follows: if source - file contains program then unit_type = FPM_UNIT_PROGRAM else if source - file contains non - module subroutine / function then unit_type = FPM_UNIT_SUBPROGRAM else if source - file contains submodule then unit_type = FPM_UNIT_SUBMODULE else if source - file contains module then unit_type = FPM_UNIT_MODULE end if @note Note\n A source file is only designated FPM_UNIT_MODULE if it only contains modules - no non-module subprograms.\n (This allows tree-shaking/pruning of build targets based on unused module dependencies.) Source scope: FPM_SCOPE_* Describes the scoping rules for using modules — controls module dependency resolution Uses fpm_toml fpm_dependency fpm_strings fpm_compiler iso_fortran_env fpm_error fpm_manifest_preprocess Variables Type Visibility Attributes Name Initial integer, public, parameter :: FPM_SCOPE_APP = 3 Module-use scope is library/dependency and app modules integer, public, parameter :: FPM_SCOPE_DEP = 2 Module-use scope is library/dependency modules only integer, public, parameter :: FPM_SCOPE_EXAMPLE = 5 integer, public, parameter :: FPM_SCOPE_LIB = 1 Module-use scope is library/dependency modules only integer, public, parameter :: FPM_SCOPE_TEST = 4 Module-use scope is library/dependency and test modules integer, public, parameter :: FPM_SCOPE_UNKNOWN = -1 Source has no module-use scope integer, public, parameter :: FPM_UNIT_CHEADER = 6 Source type is c header file integer, public, parameter :: FPM_UNIT_CPPSOURCE = 7 Souce type is c++ source file. integer, public, parameter :: FPM_UNIT_CSOURCE = 5 Source type is c source file integer, public, parameter :: FPM_UNIT_MODULE = 2 Source only contains one or more fortran modules integer, public, parameter :: FPM_UNIT_PROGRAM = 1 Source contains a fortran program integer, public, parameter :: FPM_UNIT_SUBMODULE = 3 Source contains one or more fortran submodules integer, public, parameter :: FPM_UNIT_SUBPROGRAM = 4 Source contains one or more fortran subprogram not within modules integer, public, parameter :: FPM_UNIT_UNKNOWN = -1 Source type unknown Derived Types type, public, extends( serializable_t ) :: fortran_features_t Enabled Fortran language features Components Type Visibility Attributes Name Initial logical, public :: implicit_external = .false. Use implicit external interface logical, public :: implicit_typing = .false. Use default implicit typing character(len=:), public, allocatable :: source_form Form to use for all Fortran sources Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => fft_dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => fft_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => fft_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: fpm_model_t Type describing everything required to build\n the root package and its dependencies. Components Type Visibility Attributes Name Initial type( archiver_t ), public :: archiver Archiver object character(len=:), public, allocatable :: build_prefix Base directory for build character(len=:), public, allocatable :: c_compile_flags Command line flags passed to C for compilation type( compiler_t ), public :: compiler Compiler object character(len=:), public, allocatable :: cxx_compile_flags Command line flags passed to C++ for compilation type( dependency_tree_t ), public :: deps Project dependencies logical, public :: enforce_module_names = .false. Whether module names should be prefixed with the package name type( string_t ), public, allocatable :: external_modules (:) External modules used character(len=:), public, allocatable :: fortran_compile_flags Command line flags passed to fortran for compilation type( string_t ), public, allocatable :: include_dirs (:) Include directories logical, public :: include_tests = .true. Whether tests should be added to the build list character(len=:), public, allocatable :: link_flags Command line flags passed to the linker type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public :: module_prefix Prefix for all module names character(len=:), public, allocatable :: package_name Name of root package type( package_t ), public, allocatable :: packages (:) Array of packages (including the root package) Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => model_dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => model_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => model_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: package_t Type for describing a single package Components Type Visibility Attributes Name Initial logical, public :: enforce_module_names = .false. Module naming conventions type( fortran_features_t ), public :: features Language features type( string_t ), public :: module_prefix Prefix for all module names character(len=:), public, allocatable :: name Name of package type( preprocess_config_t ), public :: preprocess List of macros. type( srcfile_t ), public, allocatable :: sources (:) Array of sources character(len=:), public, allocatable :: version Package version number. Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => package_dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => package_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => package_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: srcfile_t Type for describing a source file Components Type Visibility Attributes Name Initial integer(kind=int64), public :: digest Current hash character(len=:), public, allocatable :: exe_name Name of executable for FPM_UNIT_PROGRAM character(len=:), public, allocatable :: file_name File path relative to cwd type( string_t ), public, allocatable :: include_dependencies (:) Files INCLUDEd by this source file type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public, allocatable :: modules_provided (:) Modules provided by this source file (lowerstring) type( string_t ), public, allocatable :: modules_used (:) Modules USEd by this source file (lowerstring) type( string_t ), public, allocatable :: parent_modules (:) Parent modules (submodules only) integer, public :: unit_scope = FPM_SCOPE_UNKNOWN Target module-use scope integer, public :: unit_type = FPM_UNIT_UNKNOWN Type of source unit Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => srcfile_dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => srcfile_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => srcfile_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public function FPM_SCOPE_NAME (flag) result(name) Return the character name of a scope flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: flag Return Value character(len=:), allocatable Subroutines public subroutine show_model (model) Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(in) :: model","tags":"","loc":"module/fpm_model.html"},{"title":"fpm_sources – Fortran-lang/fpm","text":"Discovery of sources This module implements subroutines for building a list of [[srcfile_t]] objects by looking for source files in the filesystem. Uses fpm_manifest_executable fpm_environment fpm_source_parsing fpm_model fpm_strings fpm_error fpm_filesystem Functions public function get_exe_name_with_suffix (source) result(suffixed) Build an executable name with suffix. Safe routine that always returns an allocated string Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(in) :: source Return Value character(len=:), allocatable Subroutines public subroutine add_executable_sources (sources, executables, scope, auto_discover, with_f_ext, error) Add to sources using the executable and test entries in the manifest and\napplies any executable-specific overrides such as executable%name .\nAdds all sources (including modules) from each executable%source_dir Compare lowercase strings to allow auto-discovery of pre-processed extensions Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(inout), allocatable, target :: sources (:) List of [[srcfile_t]] objects to append to. Allocated if not allocated class( executable_config_t ), intent(in) :: executables (:) List of [[executable_config_t]] entries from manifest integer, intent(in) :: scope Scope to apply to the discovered sources: either FPM_SCOPE_APP or FPM_SCOPE_TEST , see fpm_model logical, intent(in) :: auto_discover If .false. only executables and tests specified in the manifest are added to sources type( string_t ), intent(in), optional :: with_f_ext (:) Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type( error_t ), intent(out), allocatable :: error Error handling public subroutine add_sources_from_dir (sources, directory, scope, with_executables, with_f_ext, recurse, error) Add to sources by looking for source files in directory Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(inout), allocatable, target :: sources (:) List of [[srcfile_t]] objects to append to. Allocated if not allocated character(len=*), intent(in) :: directory Directory in which to search for source files integer, intent(in) :: scope Scope to apply to the discovered sources, see fpm_model for enumeration logical, intent(in), optional :: with_executables Executable sources (fortran program s) are ignored unless with_executables=.true. type( string_t ), intent(in), optional :: with_f_ext (:) Additional user-defined (preprocessor) extensions that should be treated as Fortran sources logical, intent(in), optional :: recurse Whether to recursively search subdirectories, default is .true. type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_sources.html"},{"title":"fpm_manifest_library – Fortran-lang/fpm","text":"Implementation of the meta data for libraries. A library table can currently have the following fields [library] source-dir = \"path\" include-dir = [ \"path1\" , \"path2\" ] build-script = \"file\" Uses fpm_strings fpm_toml fpm_error Derived Types type, public, extends( serializable_t ) :: library_config_t Configuration meta data for a library Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: build_script Alternative build script to be invoked type( string_t ), public, allocatable :: include_dir (:) Include path prefix character(len=:), public, allocatable :: source_dir Source path prefix Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => library_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_library (self, table, error) Construct a new library configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( library_config_t ), intent(out) :: self Instance of the library configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_library.html"},{"title":"fpm_source_parsing – Fortran-lang/fpm","text":"Parsing of package source files This module exposes two functions, [[parse_f_source]] and [[parse_c_source]] ,\n which perform a rudimentary parsing of fortran and c source files\n in order to extract information required for module dependency tracking. Both functions additionally calculate and store a file digest (hash) which\n is used by the backend ( fpm_backend ) to skip compilation of unmodified sources. Both functions return an instance of the srcfile_t type. For more information, please read the documentation for each function: [[parse_f_source]] [[parse_c_source]] Uses fpm_strings fpm_filesystem fpm_error fpm_model Functions public function parse_c_source (c_filename, error) result(c_source) Parsing of c, cpp source files Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: c_filename type( error_t ), intent(out), allocatable :: error Return Value type( srcfile_t ) public function parse_f_source (f_filename, error) result(f_source) Parsing of free-form fortran source files Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_filename type( error_t ), intent(out), allocatable :: error Return Value type( srcfile_t ) Subroutines public subroutine parse_use_statement (f_filename, i, line, use_stmt, is_intrinsic, module_name, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_filename Current file name and line number (for error messaging) integer, intent(in) :: i character(len=*), intent(in) :: line The line being parsed. MUST BE preprocessed with trim(adjustl() logical, intent(out) :: use_stmt Does this line contain a use statement? logical, intent(out) :: is_intrinsic Is the module in this statement intrinsic? character(len=:), intent(out), allocatable :: module_name used module name type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_source_parsing.html"},{"title":"fpm_error – Fortran-lang/fpm","text":"Implementation of basic error handling. Uses fpm_strings iso_fortran_env Derived Types type, public :: error_t Data type defining an error Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: message Error message Functions public function bad_name_error (error, label, name) Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: label Error message label to add to message character(len=*), intent(in) :: name name value to check Return Value logical Subroutines public subroutine fatal_error (error, message) Generic fatal runtime error Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: message Error message public subroutine file_not_found_error (error, file_name) Error created when a file is missing or not found Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: file_name Name of the missing file public subroutine file_parse_error (error, file_name, message, line_num, line_string, line_col) Error created when file parsing fails Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: file_name Name of file character(len=*), intent(in) :: message Parse error message integer, intent(in), optional :: line_num Line number of parse error character(len=*), intent(in), optional :: line_string Line context string integer, intent(in), optional :: line_col Line context column public subroutine fpm_stop (value, message) Arguments Type Intent Optional Attributes Name integer, intent(in) :: value value to use on STOP character(len=*), intent(in) :: message Error message public subroutine syntax_error (error, message) Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: message Error message","tags":"","loc":"module/fpm_error.html"},{"title":"fpm_versioning – Fortran-lang/fpm","text":"Implementation of versioning data for comparing packages Uses fpm_strings fpm_error regex_module Interfaces public interface new_version private subroutine new_version_from_string(self, string, error) Create a new version from a string Arguments Type Intent Optional Attributes Name type( version_t ), intent(out) :: self Instance of the versioning data character(len=*), intent(in) :: string String describing the version information type( error_t ), intent(out), allocatable :: error Error handling private subroutine new_version_from_int(self, num) Create a new version from a string Arguments Type Intent Optional Attributes Name type( version_t ), intent(out) :: self Instance of the versioning data integer, intent(in) :: num (:) Subversion numbers to define version data Derived Types type, public :: version_t Type-Bound Procedures generic, public :: operator(.match.) => match ../../ Compare a version against a version constraint (x.x.0 <= v < x.x.HUGE) generic, public :: operator(/=) => not_equals generic, public :: operator(<) => less generic, public :: operator(<=) => less_equals generic, public :: operator(==) => equals generic, public :: operator(>) => greater generic, public :: operator(>=) => greater_equals procedure, public :: s ../../ Create a printable string from a version data type Functions public function regex_version_from_text (text, what, error) result(ver) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: text character(len=*), intent(in) :: what type( error_t ), intent(out), allocatable :: error Return Value type( string_t )","tags":"","loc":"module/fpm_versioning.html"},{"title":"fpm_manifest_executable – Fortran-lang/fpm","text":"Implementation of the meta data for an executables. An executable table can currently have the following fields [[ executable ]] name = \"string\" source-dir = \"path\" main = \"file\" link = [ \"lib\" ] [executable.dependencies] Uses fpm_strings fpm_manifest_dependency fpm_toml fpm_error Derived Types type, public, extends( serializable_t ) :: executable_config_t Configuation meta data for an executable Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => exe_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_executable (self, table, error) Construct a new executable configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( executable_config_t ), intent(out) :: self Instance of the executable configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_executable.html"},{"title":"fpm_cmd_update – Fortran-lang/fpm","text":"Uses fpm_toml fpm_manifest fpm_dependency fpm_command_line fpm_error fpm_filesystem Subroutines public subroutine cmd_update (settings) Entry point for the update subcommand Arguments Type Intent Optional Attributes Name type( fpm_update_settings ), intent(in) :: settings Representation of the command line arguments","tags":"","loc":"module/fpm_cmd_update.html"},{"title":"fpm_manifest_example – Fortran-lang/fpm","text":"Implementation of the meta data for an example. The example data structure is effectively a decorated version of an executable\n and shares most of its properties, except for the defaults and can be\n handled under most circumstances just like any other executable. A example table can currently have the following fields [[ example ]] name = \"string\" source-dir = \"path\" main = \"file\" link = [ \"lib\" ] [example.dependencies] Uses fpm_manifest_dependency fpm_toml fpm_manifest_executable fpm_error Derived Types type, public, extends( executable_config_t ) :: example_config_t Configuation meta data for an example Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => exe_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_example (self, table, error) Construct a new example configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( example_config_t ), intent(out) :: self Instance of the example configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_example.html"},{"title":"fpm_compiler – Fortran-lang/fpm","text":"Define compiler command options This module defines compiler options to use for the debug and release builds. Uses fpm_environment fpm_toml fpm_manifest fpm_strings iso_fortran_env fpm_error fpm_filesystem Variables Type Visibility Attributes Name Initial integer, public, parameter :: compiler_enum = kind(id_unknown) character(len=*), public, parameter :: flag_cray_fixed_form = \" -ffixed\" character(len=*), public, parameter :: flag_cray_free_form = \" -ffree\" character(len=*), public, parameter :: flag_cray_implicit_typing = \" -el\" character(len=*), public, parameter :: flag_cray_no_implicit_typing = \" -dl\" character(len=*), public, parameter :: flag_gnu_backtrace = \" -fbacktrace\" character(len=*), public, parameter :: flag_gnu_check = \" -fcheck=bounds -fcheck=array-temps\" character(len=*), public, parameter :: flag_gnu_coarray = \" -fcoarray=single\" character(len=*), public, parameter :: flag_gnu_debug = \" -g\" character(len=*), public, parameter :: flag_gnu_external = \" -Wimplicit-interface\" character(len=*), public, parameter :: flag_gnu_fixed_form = \" -ffixed-form\" character(len=*), public, parameter :: flag_gnu_free_form = \" -ffree-form\" character(len=*), public, parameter :: flag_gnu_limit = \" -fmax-errors=1\" character(len=*), public, parameter :: flag_gnu_no_implicit_external = \" -Werror=implicit-interface\" character(len=*), public, parameter :: flag_gnu_no_implicit_typing = \" -fimplicit-none\" character(len=*), public, parameter :: flag_gnu_openmp = \" -fopenmp\" character(len=*), public, parameter :: flag_gnu_opt = \" -O3 -funroll-loops\" character(len=*), public, parameter :: flag_gnu_pic = \" -fPIC\" character(len=*), public, parameter :: flag_gnu_warn = \" -Wall -Wextra\" character(len=*), public, parameter :: flag_ibmxl_backslash = \" -qnoescape\" character(len=*), public, parameter :: flag_intel_align = \" -align all\" character(len=*), public, parameter :: flag_intel_align_win = \" /align:all\" character(len=*), public, parameter :: flag_intel_backtrace = \" -traceback\" character(len=*), public, parameter :: flag_intel_backtrace_win = \" /traceback\" character(len=*), public, parameter :: flag_intel_byterecl = \" -assume byterecl\" character(len=*), public, parameter :: flag_intel_byterecl_win = \" /assume:byterecl\" character(len=*), public, parameter :: flag_intel_check = \" -check all\" character(len=*), public, parameter :: flag_intel_check_win = \" /check:all\" character(len=*), public, parameter :: flag_intel_debug = \" -O0 -g\" character(len=*), public, parameter :: flag_intel_debug_win = \" /Od /Z7\" character(len=*), public, parameter :: flag_intel_fixed_form = \" -fixed\" character(len=*), public, parameter :: flag_intel_fixed_form_win = \" /fixed\" character(len=*), public, parameter :: flag_intel_fp = \" -fp-model precise -pc64\" character(len=*), public, parameter :: flag_intel_fp_win = \" /fp:precise\" character(len=*), public, parameter :: flag_intel_free_form = \" -free\" character(len=*), public, parameter :: flag_intel_free_form_win = \" /free\" character(len=*), public, parameter :: flag_intel_limit = \" -error-limit 1\" character(len=*), public, parameter :: flag_intel_limit_win = \" /error-limit:1\" character(len=*), public, parameter :: flag_intel_llvm_check = \" -check all,nouninit\" character(len=*), public, parameter :: flag_intel_nogen = \" -nogen-interfaces\" character(len=*), public, parameter :: flag_intel_nogen_win = \" /nogen-interfaces\" character(len=*), public, parameter :: flag_intel_openmp = \" -qopenmp\" character(len=*), public, parameter :: flag_intel_openmp_win = \" /Qopenmp\" character(len=*), public, parameter :: flag_intel_opt = \" -O3\" character(len=*), public, parameter :: flag_intel_opt_win = \" /O3\" character(len=*), public, parameter :: flag_intel_pthread = \" -reentrancy threaded\" character(len=*), public, parameter :: flag_intel_pthread_win = \" /reentrancy:threaded\" character(len=*), public, parameter :: flag_intel_standard_compliance = \" -standard-semantics\" character(len=*), public, parameter :: flag_intel_standard_compliance_win = \" /standard-semantics\" character(len=*), public, parameter :: flag_intel_warn = \" -warn all\" character(len=*), public, parameter :: flag_intel_warn_win = \" /warn:all\" character(len=*), public, parameter :: flag_lfortran_fixed_form = \" --fixed-form\" character(len=*), public, parameter :: flag_lfortran_implicit_external = \" --implicit-interface\" character(len=*), public, parameter :: flag_lfortran_implicit_typing = \" --implicit-typing\" character(len=*), public, parameter :: flag_lfortran_openmp = \" --openmp\" character(len=*), public, parameter :: flag_lfortran_opt = \" --fast\" character(len=*), public, parameter :: flag_nag_backtrace = \" -gline\" character(len=*), public, parameter :: flag_nag_check = \" -C\" character(len=*), public, parameter :: flag_nag_coarray = \" -coarray=single\" character(len=*), public, parameter :: flag_nag_debug = \" -g -O0\" character(len=*), public, parameter :: flag_nag_fixed_form = \" -fixed\" character(len=*), public, parameter :: flag_nag_free_form = \" -free\" character(len=*), public, parameter :: flag_nag_no_implicit_typing = \" -u\" character(len=*), public, parameter :: flag_nag_openmp = \" -openmp\" character(len=*), public, parameter :: flag_nag_opt = \" -O4\" character(len=*), public, parameter :: flag_nag_pic = \" -PIC\" character(len=*), public, parameter :: flag_pgi_backslash = \" -Mbackslash\" character(len=*), public, parameter :: flag_pgi_check = \" -Mbounds -Mchkptr -Mchkstk\" character(len=*), public, parameter :: flag_pgi_debug = \" -g\" character(len=*), public, parameter :: flag_pgi_fixed_form = \" -Mfixed\" character(len=*), public, parameter :: flag_pgi_free_form = \" -Mfree\" character(len=*), public, parameter :: flag_pgi_openmp = \" -mp\" character(len=*), public, parameter :: flag_pgi_traceback = \" -traceback\" character(len=*), public, parameter :: flag_pgi_warn = \" -Minform=inform\" Enumerations enum, bind(c) Enumerators enumerator :: id_unknown = 0 enumerator :: id_gcc = 1 enumerator :: id_f95 = 2 enumerator :: id_caf = 3 enumerator :: id_intel_classic_nix = 4 enumerator :: id_intel_classic_mac = 5 enumerator :: id_intel_classic_windows = 6 enumerator :: id_intel_llvm_nix = 7 enumerator :: id_intel_llvm_windows = 8 enumerator :: id_intel_llvm_unknown = 9 enumerator :: id_pgi = 10 enumerator :: id_nvhpc = 11 enumerator :: id_nag = 12 enumerator :: id_flang = 13 enumerator :: id_flang_new = 14 enumerator :: id_f18 = 15 enumerator :: id_ibmxl = 16 enumerator :: id_cray = 17 enumerator :: id_lahey = 18 enumerator :: id_lfortran = 19 Interfaces public interface debug Create debug printout public pure function debug_compiler (self) result(repr) String representation of a compiler object Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string public pure function debug_archiver (self) result(repr) String representation of an archiver object Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(in) :: self Instance of the archiver object Return Value character(len=:), allocatable Representation as string Derived Types type, public, extends( serializable_t ) :: archiver_t Definition of archiver object Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: ar Path to archiver logical, public :: echo = .true. Print all command logical, public :: use_response_file = .false. Use response files to pass arguments logical, public :: verbose = .true. Verbose output of command Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml procedure, public :: make_archive ../../ Create static archive generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => ar_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: compiler_t Definition of compiler object Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: cc Path to the C compiler character(len=:), public, allocatable :: cxx Path to the C++ compiler logical, public :: echo = .true. Print all commands character(len=:), public, allocatable :: fc Path to the Fortran compiler integer(kind=compiler_enum), public :: id = id_unknown Identifier of the compiler logical, public :: verbose = .true. Verbose output of command Type-Bound Procedures procedure, public :: check_fortran_source_runs ../../ Fortran feature support procedure, public :: compile_c ../../ Compile a C object procedure, public :: compile_cpp ../../ Compile a CPP object procedure, public :: compile_fortran ../../ Compile a Fortran object generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => compiler_dump procedure, public :: enumerate_libraries ../../ Enumerate libraries, based on compiler and platform procedure, public :: get_default_flags ../../ Get default compiler flags procedure, public :: get_feature_flag ../../ Get feature flag procedure, public :: get_include_flag ../../ Get flag for include directories procedure, public :: get_main_flags ../../ Get flags for the main linking command procedure, public :: get_module_flag ../../ Get flag for module output directories procedure, public :: is_gnu ../../ Check whether this is a GNU compiler procedure, public :: is_intel ../../ Check whether this is an Intel compiler procedure, public :: is_unknown ../../ Check whether compiler is recognized procedure, public :: link ../../ Link executable generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => compiler_load procedure, public :: name => compiler_name ../../ Return compiler name generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => compiler_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip procedure, public :: with_qp procedure, public :: with_xdp Functions public function ar_is_same (this, that) Check that two archiver_t objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical public function check_compiler (compiler, expected) result(match) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler character(len=*), intent(in) :: expected Return Value logical public function check_fortran_source_runs (self, input) result(success) Run a single-source Fortran program using the current compiler\nCompile a Fortran object\nCreate temporary source file\nWrite contents\nCompile and link program\nRun and retrieve exit code Read more… Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Program Source Return Value logical public function compiler_is_same (this, that) Check that two compiler_t objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical public pure function compiler_name (self) result(name) Return a compiler name string Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string public pure function debug_archiver (self) result(repr) String representation of an archiver object Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(in) :: self Instance of the archiver object Return Value character(len=:), allocatable Representation as string public pure function debug_compiler (self) result(repr) String representation of a compiler object Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string public function enumerate_libraries (self, prefix, libs) result(r) Enumerate libraries, based on compiler and platform Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: prefix type( string_t ), intent(in) :: libs (:) Return Value character(len=:), allocatable public function get_compiler_id (compiler) result(id) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler Return Value integer(kind=compiler_enum) public function get_default_flags (self, release) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self logical, intent(in) :: release Return Value character(len=:), allocatable public function get_feature_flag (self, feature) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: feature Return Value character(len=:), allocatable public function get_id (compiler) result(id) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler Return Value integer(kind=compiler_enum) public function get_include_flag (self, path) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function get_macros (id, macros_list, version) result(macros) This function will parse and read the macros list and\nreturn them as defined flags.\nSet macro defintion symbol on the basis of compiler used\nCheck if macros are not allocated.\nSplit the macro name and value. Read more… Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id type( string_t ), intent(in), allocatable :: macros_list (:) character(len=:), intent(in), allocatable :: version Return Value character(len=:), allocatable public function get_module_flag (self, path) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable public pure function is_gnu (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical public pure function is_intel (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical public pure function is_unknown (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical public function with_qp (self) Check if the current compiler supports 128-bit real precision Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical public function with_xdp (self) Check if the current compiler supports 80-bit “extended” real precision Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical Subroutines public subroutine compile_c (self, input, output, args, log_file, stat) Compile a C object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine compile_cpp (self, input, output, args, log_file, stat) Compile a CPP object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine compile_fortran (self, input, output, args, log_file, stat) Compile a Fortran object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine compiler_dump (self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine compiler_load (self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine dump_to_toml (self, table, error) Dump dependency to toml table Read more… Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine get_debug_compile_flags (id, flags) Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(out), allocatable :: flags public subroutine get_default_c_compiler (f_compiler, c_compiler) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_compiler character(len=:), intent(out), allocatable :: c_compiler public subroutine get_default_cxx_compiler (f_compiler, cxx_compiler) Get C++ Compiler. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_compiler character(len=:), intent(out), allocatable :: cxx_compiler public subroutine get_main_flags (self, language, flags) Get special flags for the main linker Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: language character(len=:), intent(out), allocatable :: flags public subroutine get_release_compile_flags (id, flags) Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(out), allocatable :: flags public subroutine link (self, output, args, log_file, stat) Link an executable Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine load_from_toml (self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine make_archive (self, output, args, log_file, stat) Create an archive Read more… Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: self Instance of the archiver object character(len=*), intent(in) :: output Name of the archive to generate type( string_t ), intent(in) :: args (:) Object files to include into the archive character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine new_archiver (self, ar, echo, verbose) Create new archiver instance Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(out) :: self New instance of the archiver character(len=*), intent(in) :: ar User provided archiver command logical, intent(in) :: echo Echo compiler command logical, intent(in) :: verbose Verbose mode: dump compiler output public subroutine new_compiler (self, fc, cc, cxx, echo, verbose) Create new compiler instance Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(out) :: self New instance of the compiler character(len=*), intent(in) :: fc Fortran compiler name or path character(len=*), intent(in) :: cc C compiler name or path character(len=*), intent(in) :: cxx C++ Compiler name or path logical, intent(in) :: echo Echo compiler command logical, intent(in) :: verbose Verbose mode: dump compiler output public pure subroutine set_cpp_preprocessor_flags (id, flags) Modify the flag_cpp_preprocessor on the basis of the compiler. Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(inout), allocatable :: flags public subroutine write_response_file (name, argv) Response files allow to read command line options from files.\nWhitespace is used to separate the arguments, we will use newlines\nas separator to create readable response files which can be inspected\nin case of errors. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name type( string_t ), intent(in) :: argv (:)","tags":"","loc":"module/fpm_compiler.html"},{"title":"fpm_command_line – Fortran-lang/fpm","text":"Definition of the command line interface This module uses M_CLI2 to define\n the command line interface.\n To define a command line interface create a new command settings type\n from the fpm_cmd_settings base class or the respective parent command\n settings. The subcommand is selected by the first non-option argument in the command\n line. In the subcase block the actual command line is defined and transferred\n to an instance of the fpm_cmd_settings , the actual type is used by the fpm main program to determine which command entry point is chosen. To add a new subcommand add a new case to select construct and specify the\n wanted command line and the expected default values.\n Some of the following points also apply if you add a new option or argument\n to an existing fpm subcommand.\n At this point you should create a help page for the new command in a simple\n catman-like format as well in the set_help procedure.\n Make sure to register new subcommands in the fpm-manual command by adding\n them to the manual character array and in the help/manual case as well.\n You should add the new command to the synopsis section of the fpm-list , fpm-help and fpm --list help pages below to make sure the help output\n is complete and consistent as well. Uses fpm_environment fpm_os M_CLI2 fpm_strings fpm_release iso_fortran_env fpm_error fpm_filesystem Derived Types type, public, extends( fpm_cmd_settings ) :: fpm_build_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_cmd_settings ) :: fpm_clean_settings Components Type Visibility Attributes Name Initial logical, public :: clean_all = .false. logical, public :: clean_skip = .false. logical, public :: registry_cache = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, abstract :: fpm_cmd_settings Components Type Visibility Attributes Name Initial logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_build_settings ) :: fpm_export_settings Settings for exporting model data Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: dump_dependencies character(len=:), public, allocatable :: dump_manifest character(len=:), public, allocatable :: dump_model character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_build_settings ) :: fpm_install_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: bindir logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: includedir character(len=:), public, allocatable :: ldflag character(len=:), public, allocatable :: libdir logical, public :: list = .false. logical, public :: no_rebuild character(len=:), public, allocatable :: prefix character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_cmd_settings ) :: fpm_new_settings Components Type Visibility Attributes Name Initial logical, public :: backfill = .true. character(len=:), public, allocatable :: name logical, public :: verbose = .true. logical, public :: with_bare = .false. logical, public :: with_example = .false. logical, public :: with_executable = .false. logical, public :: with_full = .false. logical, public :: with_lib = .true. logical, public :: with_test = .false. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_build_settings ) :: fpm_publish_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag logical, public :: is_dry_run = .false. character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: show_package_version = .false. logical, public :: show_upload_data = .false. character(len=:), public, allocatable :: token logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_build_settings ) :: fpm_run_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: args logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump logical, public :: example character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=ibug), public, allocatable :: name (:) character(len=:), public, allocatable :: profile logical, public :: prune = .true. character(len=:), public, allocatable :: runner character(len=:), public, allocatable :: runner_args logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Type-Bound Procedures procedure, public :: name_ID procedure, public :: runner_command type, public, extends( fpm_run_settings ) :: fpm_test_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: args logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump logical, public :: example character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=ibug), public, allocatable :: name (:) character(len=:), public, allocatable :: profile logical, public :: prune = .true. character(len=:), public, allocatable :: runner character(len=:), public, allocatable :: runner_args logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Type-Bound Procedures procedure, public :: name_ID procedure, public :: runner_command type, public, extends( fpm_cmd_settings ) :: fpm_update_settings Settings for interacting and updating with project dependencies Components Type Visibility Attributes Name Initial logical, public :: clean character(len=:), public, allocatable :: dump logical, public :: fetch_only character(len=ibug), public, allocatable :: name (:) logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Functions public function get_fpm_env (env, default) result(val) Get an environment variable for fpm, this routine ensures that every variable\nused by fpm is prefixed with FPM_. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: env character(len=*), intent(in) :: default Return Value character(len=:), allocatable Subroutines public subroutine get_command_line_settings (cmd_settings) ! canon_path is not converting “.”, etc.\n& ‘ unknown help topic “’//trim(unnamed(i)).’not found in:’,manual] Arguments Type Intent Optional Attributes Name class( fpm_cmd_settings ), intent(out), allocatable :: cmd_settings","tags":"","loc":"module/fpm_command_line.html"},{"title":"fpm_cmd_new – Fortran-lang/fpm","text":"Definition of the “new” subcommand A type of the general command base class fpm_cmd_settings was created for the “new” subcommand ==> type fpm_new_settings .\n This procedure read the values that were set on the command line\n from this type to decide what actions to take. It is virtually self-contained and so independant of the rest of the\n application that it could function as a separate program. The “new” subcommand options currently consist of a SINGLE top\n directory name to create that must have a name that is an\n allowable Fortran variable name. That should have been ensured\n by the command line processing before this procedure is called.\n So basically this routine has already had the options vetted and\n just needs to conditionally create a few files. As described in the documentation it will selectively\n create the subdirectories app/, test/, src/, and example/\n and populate them with sample files. It also needs to create an initial manifest file “fpm.toml”. It then calls the system command “git init”. It should test for file existence and not overwrite existing\n files and inform the user if there were conflicts. Any changes should be reflected in the documentation in fpm_command_line.f90 FUTURE\n A filename like “.” would need system commands or a standard routine\n like realpath(3c) to process properly. Perhaps allow more than one name on a single command. It is an arbitrary\n restriction based on a concensus preference, not a required limitation. Initially the name of the directory is used as the module name in the\n src file so it must be an allowable Fortran variable name. If there are\n complaints about it it might be changed. Handling unicode at this point\n might be problematic as not all current compilers handle it. Other\n utilities like content trackers (ie. git) or repositories like github\n might also have issues with alternative names or names with spaces, etc.\n So for the time being it seems prudent to encourage simple ASCII top directory\n names (similiar to the primary programming language Fortran itself). Should be able to create or pull more complicated initial examples\n based on various templates. It should place or mention other relevant\n documents such as a description of the manifest file format in user hands;\n or how to access registered packages and local packages,\n although some other command might provide that (and the help command should\n be the first go-to for a CLI utility). Uses fpm_environment fpm_strings fpm_command_line iso_fortran_env fpm_error fpm_filesystem Subroutines public subroutine cmd_new (settings) TOP DIRECTORY NAME PROCESSING\nsee if requested new directory already exists and process appropriately\ntemporarily change to new directory as a test. NB: System dependent Arguments Type Intent Optional Attributes Name type( fpm_new_settings ), intent(in) :: settings","tags":"","loc":"module/fpm_cmd_new.html"},{"title":"fpm_manifest_metapackages – Fortran-lang/fpm","text":"Implementation of the metapackage configuration data. A metapackage table can currently have the following fields [metapackages] fpm = \"0.1.0\" openmp = bool stdlib = bool Uses fpm_environment fpm_toml fpm_error Derived Types type, public :: metapackage_config_t Configuration data for metapackages Components Type Visibility Attributes Name Initial type( metapackage_request_t ), public :: hdf5 HDF5 type( metapackage_request_t ), public :: minpack fortran-lang minpack type( metapackage_request_t ), public :: mpi Request MPI support type( metapackage_request_t ), public :: openmp Request OpenMP support type( metapackage_request_t ), public :: stdlib Request stdlib support type, public :: metapackage_request_t Configuration data for a single metapackage request Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: name Metapackage name logical, public :: on = .false. Request flag character(len=:), public, allocatable :: version Version Specification string Functions public function is_meta_package (key) Check local schema for allowed entries Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: key Instance of the TOML data structure Return Value logical Subroutines public subroutine new_meta_config (self, table, meta_allowed, error) Construct a new build configuration from a TOML data structure Read more… Arguments Type Intent Optional Attributes Name type( metapackage_config_t ), intent(out) :: self Instance of the build configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure logical, intent(in) :: meta_allowed (:) List of keys allowed to be metapackages type( error_t ), intent(out), allocatable :: error Error handling public subroutine new_meta_request (self, key, table, meta_allowed, error) Construct a new metapackage request from the dependencies table Read more… Arguments Type Intent Optional Attributes Name type( metapackage_request_t ), intent(out) :: self character(len=*), intent(in) :: key The package name type(toml_table), intent(inout) :: table Instance of the TOML data structure logical, intent(in), optional :: meta_allowed (:) List of keys allowed to be metapackages type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_metapackages.html"},{"title":"fpm – Fortran-lang/fpm","text":"Uses fpm_toml fpm_sources fpm_environment fpm_manifest fpm_model fpm_dependency fpm_strings fpm_backend iso_c_binding fpm_command_line fpm_compiler iso_fortran_env fpm_targets fpm_meta fpm_settings fpm_error fpm_filesystem Subroutines public subroutine build_model (model, settings, package, error) Constructs a valid fpm model from command line settings and the toml manifest.\nAdd this dependency’s manifest macros Read more… Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(out) :: model class( fpm_build_settings ), intent(inout) :: settings type( package_config_t ), intent(inout) :: package type( error_t ), intent(out), allocatable :: error public subroutine check_modules_for_duplicates (model, duplicates_found) Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(in) :: model logical :: duplicates_found public subroutine cmd_build (settings) Dump model to file Arguments Type Intent Optional Attributes Name type( fpm_build_settings ), intent(inout) :: settings public subroutine cmd_clean (settings) Delete the build directory including or excluding dependencies. Can be used\nto clear the registry cache. Arguments Type Intent Optional Attributes Name class( fpm_clean_settings ), intent(in) :: settings Settings for the clean command. public subroutine cmd_run (settings, test) Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(inout) :: settings logical, intent(in) :: test","tags":"","loc":"module/fpm.html"},{"title":"fpm_cmd_export – Fortran-lang/fpm","text":"Uses fpm_toml fpm_manifest fpm_model fpm_dependency fpm_command_line fpm fpm_error fpm_filesystem Subroutines public subroutine cmd_export (settings) Entry point for the export subcommand\nRead in manifest\nExport manifest\nExport dependency tree Read more… Arguments Type Intent Optional Attributes Name type( fpm_export_settings ), intent(inout) :: settings Representation of the command line arguments","tags":"","loc":"module/fpm_cmd_export.html"},{"title":"fpm_manifest_package – Fortran-lang/fpm","text":"Define the package data containing the meta data from the configuration file. The package data defines a Fortran type corresponding to the respective\n TOML document, after creating it from a package file no more interaction\n with the TOML document is required. Every configuration type provides it custom constructor (prefixed with new_ )\n and knows how to deserialize itself from a TOML document.\n To ensure we find no untracked content in the package file all keywords are\n checked and possible entries have to be explicitly allowed in the check function.\n If entries are mutally exclusive or interdependent inside the current table\n the check function is required to enforce this schema on the data structure. The package file root allows the following keywords name = \"string\" version = \"string\" license = \"string\" author = \"string\" maintainer = \"string\" copyright = \"string\" [library] [dependencies] [dev-dependencies] [profiles] [build] [install] [fortran] [[ executable ]] [[ example ]] [[ test ]] [extra] Uses fpm_manifest_fortran fpm_manifest_build fpm_toml fpm_manifest_library fpm_manifest_profile fpm_manifest_dependency fpm_manifest_test fpm_filesystem fpm_error fpm_versioning fpm_manifest_example fpm_manifest_install fpm_manifest_metapackages fpm_manifest_executable fpm_manifest_preprocess Derived Types type, public, extends( serializable_t ) :: package_config_t Package meta data Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: author Author meta data type( build_config_t ), public :: build Build configuration data character(len=:), public, allocatable :: copyright Copyright meta data type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data type( dependency_config_t ), public, allocatable :: dev_dependency (:) Development dependency meta data type( example_config_t ), public, allocatable :: example (:) Example meta data type( executable_config_t ), public, allocatable :: executable (:) Executable meta data type( fortran_config_t ), public :: fortran Fortran meta data type( install_config_t ), public :: install Installation configuration data type( library_config_t ), public, allocatable :: library Library meta data character(len=:), public, allocatable :: license License meta data character(len=:), public, allocatable :: maintainer Maintainer meta data type( metapackage_config_t ), public :: meta Metapackage data character(len=:), public, allocatable :: name Name of the package type( preprocess_config_t ), public, allocatable :: preprocess (:) Preprocess meta data type( profile_config_t ), public, allocatable :: profiles (:) Profiles meta data type( test_config_t ), public, allocatable :: test (:) Test meta data type( version_t ), public :: version Package version Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => manifest_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_package (self, table, root, error) Construct a new package configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( package_config_t ), intent(out) :: self Instance of the package configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_package.html"},{"title":"fpm_backend_output – Fortran-lang/fpm","text":"Build Backend Progress Output This module provides a derived type build_progress_t for printing build status\n and progress messages to the console while the backend is building the package. The build_progress_t type supports two modes: normal and plain where the former does ‘pretty’ output and the latter does not.\n The normal mode is intended for typical interactive usage whereas\n ‘plain’ mode is used with the --verbose flag or when stdout is not attached\n to a terminal (e.g. when piping or redirecting stdout ). In these cases,\n the pretty output must be suppressed to avoid control codes being output. Uses fpm_backend_console fpm_filesystem iso_fortran_env fpm_targets Interfaces public interface build_progress_t Constructor for build_progress_t private function new_build_progress(target_queue, plain_mode) result(progress) Initialise a new build progress object Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in), target :: target_queue (:) The queue of scheduled targets logical, intent(in), optional :: plain_mode Enable ‘plain’ output for progress object Return Value type( build_progress_t ) Progress object to initialise Derived Types type, public :: build_progress_t Build progress object Components Type Visibility Attributes Name Initial type( console_t ), public :: console Console object for updating console lines integer, public :: n_complete Number of completed targets integer, public :: n_target Total number of targets scheduled integer, public, allocatable :: output_lines (:) Store needed when updating previous console lines logical, public :: plain_mode = .true. ‘Plain’ output (no colors or updating) type( build_target_ptr ), public, pointer :: target_queue (:) Queue of scheduled build targets Constructor Constructor for build_progress_t private\n\n \n function new_build_progress (target_queue, plain_mode) Initialise a new build progress object Type-Bound Procedures procedure, public :: compiling_status => output_status_compiling ../../ Output ‘compiling’ status for build target procedure, public :: completed_status => output_status_complete ../../ Output ‘complete’ status for build target procedure, public :: success => output_progress_success ../../ Output finished status for whole package","tags":"","loc":"module/fpm_backend_output.html"},{"title":"fpm_manifest_build – Fortran-lang/fpm","text":"Implementation of the build configuration data. A build table can currently have the following fields [build] auto-executables = bool auto-examples = bool auto-tests = bool link = [ \"lib\" ] Uses fpm_strings fpm_toml fpm_error Derived Types type, public, extends( serializable_t ) :: build_config_t Configuration data for build Components Type Visibility Attributes Name Initial logical, public :: auto_examples = .true. Automatic discovery of examples logical, public :: auto_executables = .true. Automatic discovery of executables logical, public :: auto_tests = .true. Automatic discovery of tests type( string_t ), public, allocatable :: external_modules (:) External modules to use type( string_t ), public, allocatable :: link (:) Libraries to link against logical, public :: module_naming = .false. Enforcing of package module names type( string_t ), public :: module_prefix Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => build_conf_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_build_config (self, table, package_name, error) Construct a new build configuration from a TOML data structure Read more… Arguments Type Intent Optional Attributes Name type( build_config_t ), intent(out) :: self Instance of the build configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: package_name Package name type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_build.html"},{"title":"fpm_manifest_test – Fortran-lang/fpm","text":"Implementation of the meta data for a test. The test data structure is effectively a decorated version of an executable\n and shares most of its properties, except for the defaults and can be\n handled under most circumstances just like any other executable. A test table can currently have the following fields [[ test ]] name = \"string\" source-dir = \"path\" main = \"file\" link = [ \"lib\" ] [test.dependencies] Uses fpm_manifest_dependency fpm_toml fpm_manifest_executable fpm_error Derived Types type, public, extends( executable_config_t ) :: test_config_t Configuation meta data for an test Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => exe_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_test (self, table, error) Construct a new test configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( test_config_t ), intent(out) :: self Instance of the test configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_test.html"},{"title":"main – Fortran-lang/fpm","text":"Uses fpm_cmd_export fpm_cmd_new fpm_os fpm_cmd_install fpm_command_line fpm iso_fortran_env fpm_cmd_update fpm_cmd_publish fpm_error fpm_filesystem Variables Type Attributes Name Initial class( fpm_cmd_settings ), allocatable :: cmd_settings type( error_t ), allocatable :: error character(len=:), allocatable :: project_root character(len=:), allocatable :: pwd_start character(len=:), allocatable :: pwd_working character(len=:), allocatable :: working_dir Functions function has_manifest (dir) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir Return Value logical Subroutines subroutine get_working_dir (settings, working_dir_) Save access to working directory in settings, in case setting have not been allocated Arguments Type Intent Optional Attributes Name class( fpm_cmd_settings ), intent(in), optional :: settings character(len=:), intent(out), allocatable :: working_dir_ subroutine handle_error (error_) Arguments Type Intent Optional Attributes Name type( error_t ), intent(in), optional :: error_ Source Code program main use , intrinsic :: iso_fortran_env , only : error_unit , output_unit use fpm_command_line , only : & fpm_cmd_settings , & fpm_new_settings , & fpm_build_settings , & fpm_export_settings , & fpm_run_settings , & fpm_test_settings , & fpm_install_settings , & fpm_update_settings , & fpm_clean_settings , & fpm_publish_settings , & get_command_line_settings use fpm_error , only : error_t use fpm_filesystem , only : exists , parent_dir , join_path use fpm , only : cmd_build , cmd_run , cmd_clean use fpm_cmd_install , only : cmd_install use fpm_cmd_export , only : cmd_export use fpm_cmd_new , only : cmd_new use fpm_cmd_update , only : cmd_update use fpm_cmd_publish , only : cmd_publish use fpm_os , only : change_directory , get_current_directory implicit none class ( fpm_cmd_settings ), allocatable :: cmd_settings type ( error_t ), allocatable :: error character ( len = :), allocatable :: pwd_start , pwd_working , working_dir , project_root call get_command_line_settings ( cmd_settings ) call get_current_directory ( pwd_start , error ) call handle_error ( error ) call get_working_dir ( cmd_settings , working_dir ) if ( allocated ( working_dir )) then ! Change working directory if requested if ( len_trim ( working_dir ) > 0 ) then call change_directory ( working_dir , error ) call handle_error ( error ) call get_current_directory ( pwd_working , error ) call handle_error ( error ) write ( output_unit , '(*(a))' ) \"fpm: Entering directory '\" // pwd_working // \"'\" else pwd_working = pwd_start end if else pwd_working = pwd_start end if select type ( settings => cmd_settings ) type is ( fpm_new_settings ) class default if (. not . has_manifest ( pwd_working )) then project_root = pwd_working do while (. not . has_manifest ( project_root )) working_dir = parent_dir ( project_root ) if ( len ( working_dir ) == 0 ) exit project_root = working_dir end do if ( has_manifest ( project_root )) then call change_directory ( project_root , error ) call handle_error ( error ) write ( output_unit , '(*(a))' ) \"fpm: Entering directory '\" // project_root // \"'\" end if end if end select select type ( settings => cmd_settings ) type is ( fpm_new_settings ) call cmd_new ( settings ) type is ( fpm_build_settings ) call cmd_build ( settings ) type is ( fpm_run_settings ) call cmd_run ( settings , test = . false .) type is ( fpm_test_settings ) call cmd_run ( settings , test = . true .) type is ( fpm_export_settings ) call cmd_export ( settings ) type is ( fpm_install_settings ) call cmd_install ( settings ) type is ( fpm_update_settings ) call cmd_update ( settings ) type is ( fpm_clean_settings ) call cmd_clean ( settings ) type is ( fpm_publish_settings ) call cmd_publish ( settings ) end select if ( allocated ( project_root )) then write ( output_unit , '(*(a))' ) \"fpm: Leaving directory '\" // project_root // \"'\" end if if ( pwd_start /= pwd_working ) then write ( output_unit , '(*(a))' ) \"fpm: Leaving directory '\" // pwd_working // \"'\" end if contains function has_manifest ( dir ) character ( len =* ), intent ( in ) :: dir logical :: has_manifest has_manifest = exists ( join_path ( dir , \"fpm.toml\" )) end function has_manifest subroutine handle_error ( error_ ) type ( error_t ), optional , intent ( in ) :: error_ if ( present ( error_ )) then write ( error_unit , '(\"[Error]\", 1x, a)' ) error_ % message stop 1 end if end subroutine handle_error !> Save access to working directory in settings, in case setting have not been allocated subroutine get_working_dir ( settings , working_dir_ ) class ( fpm_cmd_settings ), optional , intent ( in ) :: settings character ( len = :), allocatable , intent ( out ) :: working_dir_ if ( present ( settings )) then working_dir_ = settings % working_dir end if end subroutine get_working_dir end program main","tags":"","loc":"program/main.html"},{"title":"manifest.f90 – Fortran-lang/fpm","text":"Source Code !> Package configuration data. !> !> This module provides the necessary procedure to translate a TOML document !> to the corresponding Fortran type, while verifying it with respect to !> its schema. !> !> Additionally, the required data types for users of this module are reexported !> to hide the actual implementation details. module fpm_manifest use fpm_manifest_example , only : example_config_t use fpm_manifest_executable , only : executable_config_t use fpm_manifest_dependency , only : dependency_config_t use fpm_manifest_library , only : library_config_t use fpm_manifest_preprocess , only : preprocess_config_t use fpm_manifest_package , only : package_config_t , new_package use fpm_error , only : error_t , fatal_error use fpm_toml , only : toml_table , read_package_file use fpm_manifest_test , only : test_config_t use fpm_filesystem , only : join_path , exists , dirname , is_dir use fpm_environment , only : os_is_unix use fpm_strings , only : string_t implicit none private public :: get_package_data , default_executable , default_library , default_test public :: default_example public :: package_config_t , dependency_config_t , preprocess_config_t contains !> Populate library in case we find the default src directory subroutine default_library ( self ) !> Instance of the library meta data type ( library_config_t ), intent ( out ) :: self self % source_dir = \"src\" self % include_dir = [ string_t ( \"include\" )] end subroutine default_library !> Populate executable in case we find the default app directory subroutine default_executable ( self , name ) !> Instance of the executable meta data type ( executable_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name self % source_dir = \"app\" self % main = \"main.f90\" end subroutine default_executable !> Populate test in case we find the default example/ directory subroutine default_example ( self , name ) !> Instance of the executable meta data type ( example_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name // \"-demo\" self % source_dir = \"example\" self % main = \"main.f90\" end subroutine default_example !> Populate test in case we find the default test/ directory subroutine default_test ( self , name ) !> Instance of the executable meta data type ( test_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name // \"-test\" self % source_dir = \"test\" self % main = \"main.f90\" end subroutine default_test !> Obtain package meta data from a configuation file subroutine get_package_data ( package , file , error , apply_defaults ) !> Parsed package meta data type ( package_config_t ), intent ( out ) :: package !> Name of the package configuration file character ( len =* ), intent ( in ) :: file !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error !> Apply package defaults (uses file system operations) logical , intent ( in ), optional :: apply_defaults type ( toml_table ), allocatable :: table character ( len = :), allocatable :: root call read_package_file ( table , file , error ) if ( allocated ( error )) return if (. not . allocated ( table )) then call fatal_error ( error , \"Unclassified error while reading: '\" // file // \"'\" ) return end if call new_package ( package , table , dirname ( file ), error ) if ( allocated ( error )) return if ( present ( apply_defaults )) then if ( apply_defaults ) then root = dirname ( file ) if ( len_trim ( root ) == 0 ) root = \".\" call package_defaults ( package , root , error ) if ( allocated ( error )) return end if end if end subroutine get_package_data !> Apply package defaults subroutine package_defaults ( package , root , error ) !> Parsed package meta data type ( package_config_t ), intent ( inout ) :: package !> Current working directory character ( len =* ), intent ( in ) :: root !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error ! Populate library in case we find the default src directory if (. not . allocated ( package % library ) . and . & & ( is_dir ( join_path ( root , \"src\" )) . or . & & is_dir ( join_path ( root , \"include\" )))) then allocate ( package % library ) call default_library ( package % library ) end if ! Populate executable in case we find the default app if (. not . allocated ( package % executable ) . and . & & exists ( join_path ( root , \"app\" , \"main.f90\" ))) then allocate ( package % executable ( 1 )) call default_executable ( package % executable ( 1 ), package % name ) end if ! Populate example in case we find the default example directory if (. not . allocated ( package % example ) . and . & & exists ( join_path ( root , \"example\" , \"main.f90\" ))) then allocate ( package % example ( 1 )) call default_example ( package % example ( 1 ), package % name ) endif ! Populate test in case we find the default test directory if (. not . allocated ( package % test ) . and . & & exists ( join_path ( root , \"test\" , \"main.f90\" ))) then allocate ( package % test ( 1 )) call default_test ( package % test ( 1 ), package % name ) endif if (. not .( allocated ( package % library ) & & . or . allocated ( package % executable ) & & . or . allocated ( package % example ) & & . or . allocated ( package % test ))) then call fatal_error ( error , \"Neither library nor executable found, there is nothing to do\" ) return end if end subroutine package_defaults end module fpm_manifest","tags":"","loc":"sourcefile/manifest.f90.html"},{"title":"install.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the installation configuration. !> !> An install table can currently have the following fields !> !>```toml !>library = bool !>``` module fpm_manifest_install use fpm_error , only : error_t , fatal_error , syntax_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , set_value , serializable_t implicit none private public :: install_config_t , new_install_config !> Configuration data for installation type , extends ( serializable_t ) :: install_config_t !> Install library with this project logical :: library = . false . contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => install_conf_same procedure :: dump_to_toml procedure :: load_from_toml end type install_config_t character ( * ), parameter , private :: class_name = 'install_config_t' contains !> Create a new installation configuration from a TOML data structure subroutine new_install_config ( self , table , error ) !> Instance of the install configuration type ( install_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"library\" , self % library , . false .) end subroutine new_install_config !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_keys ( list ) if ( size ( list ) < 1 ) return do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in install table\" ) exit case ( \"library\" ) continue end select end do if ( allocated ( error )) return end subroutine check !> Write information on install configuration instance subroutine info ( self , unit , verbosity ) !> Instance of the build configuration class ( install_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Install configuration\" write ( unit , fmt ) \" - library install\" , & & trim ( merge ( \"enabled \" , \"disabled\" , self % library )) end subroutine info logical function install_conf_same ( this , that ) class ( install_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that install_conf_same = . false . select type ( other => that ) type is ( install_config_t ) if ( this % library . neqv . other % library ) return class default ! Not the same type return end select !> All checks passed! install_conf_same = . true . end function install_conf_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( install_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_value ( table , \"library\" , self % library , error , class_name ) end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( install_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat call get_value ( table , \"library\" , self % library , error , class_name ) if ( allocated ( error )) return end subroutine load_from_toml end module fpm_manifest_install","tags":"","loc":"sourcefile/install.f90.html"},{"title":"fpm_targets.f90 – Fortran-lang/fpm","text":"Source Code !># Build target handling !> !> This module handles the construction of the build target list !> from the sources list (`[[targets_from_sources]]`), the !> resolution of module-dependencies between build targets !> (`[[resolve_module_dependencies]]`), and the enumeration of !> objects required for link targets (`[[resolve_target_linking]]`). !> !> A build target (`[[build_target_t]]`) is a file to be generated !> by the backend (compilation and linking). !> !> @note The current implementation is ignorant to the existence of !> module files (`.mod`,`.smod`). Dependencies arising from modules !> are based on the corresponding object files (`.o`) only. !> !> For more information, please read the documentation for the procedures: !> !> - `[[build_target_list]]` !> - `[[resolve_module_dependencies]]` !> !>### Enumerations !> !> __Target type:__ `FPM_TARGET_*` !> Describes the type of build target — determines backend build rules !> module fpm_targets use iso_fortran_env , only : int64 use fpm_error , only : error_t , fatal_error , fpm_stop use fpm_model use fpm_compiler , only : compiler_t use fpm_environment , only : get_os_type , OS_WINDOWS , OS_MACOS use fpm_filesystem , only : dirname , join_path , canon_path use fpm_strings , only : string_t , operator (. in .), string_cat , fnv_1a , resize , lower , str_ends_with use fpm_compiler , only : get_macros use fpm_sources , only : get_exe_name_with_suffix use fpm_manifest_preprocess , only : preprocess_config_t implicit none private public FPM_TARGET_UNKNOWN , FPM_TARGET_EXECUTABLE , & FPM_TARGET_ARCHIVE , FPM_TARGET_OBJECT , & FPM_TARGET_C_OBJECT , FPM_TARGET_CPP_OBJECT , & FPM_TARGET_NAME public build_target_t , build_target_ptr public targets_from_sources , resolve_module_dependencies public add_target , add_dependency public filter_library_targets , filter_executable_targets , filter_modules !> Target type is unknown (ignored) integer , parameter :: FPM_TARGET_UNKNOWN = - 1 !> Target type is executable integer , parameter :: FPM_TARGET_EXECUTABLE = 1 !> Target type is library archive integer , parameter :: FPM_TARGET_ARCHIVE = 2 !> Target type is compiled object integer , parameter :: FPM_TARGET_OBJECT = 3 !> Target type is c compiled object integer , parameter :: FPM_TARGET_C_OBJECT = 4 !> Target type is cpp compiled object integer , parameter :: FPM_TARGET_CPP_OBJECT = 5 !> Wrapper type for constructing arrays of `[[build_target_t]]` pointers type build_target_ptr type ( build_target_t ), pointer :: ptr => null () end type build_target_ptr !> Type describing a generated build target type build_target_t !> File path of build target object relative to cwd character (:), allocatable :: output_file !> File path of build target object relative to output_dir character (:), allocatable :: output_name !> File path of output directory character (:), allocatable :: output_dir !> File path of build log file relative to cwd character (:), allocatable :: output_log_file !> Name of parent package character (:), allocatable :: package_name !> Primary source for this build target type ( srcfile_t ), allocatable :: source !> Resolved build dependencies type ( build_target_ptr ), allocatable :: dependencies (:) !> Target type integer :: target_type = FPM_TARGET_UNKNOWN !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> Objects needed to link this target type ( string_t ), allocatable :: link_objects (:) !> Link flags for this build target character (:), allocatable :: link_flags !> Compile flags for this build target character (:), allocatable :: compile_flags !> Flag set when first visited to check for circular dependencies logical :: touched = . false . !> Flag set if build target is sorted for building logical :: sorted = . false . !> Flag set if build target will be skipped (not built) logical :: skip = . false . !> Language features type ( fortran_features_t ) :: features !> Targets in the same schedule group are guaranteed to be independent integer :: schedule = - 1 !> Previous source file hash integer ( int64 ), allocatable :: digest_cached !> List of macros type ( string_t ), allocatable :: macros (:) !> Version number character (:), allocatable :: version contains procedure :: is_executable_target end type build_target_t contains !> Target type name pure function FPM_TARGET_NAME ( type ) result ( msg ) integer , intent ( in ) :: type character (:), allocatable :: msg select case ( type ) case ( FPM_TARGET_ARCHIVE ); msg = 'Archive' case ( FPM_TARGET_CPP_OBJECT ); msg = 'C++ object' case ( FPM_TARGET_C_OBJECT ); msg = 'C Object' case ( FPM_TARGET_EXECUTABLE ); msg = 'Executable' case ( FPM_TARGET_OBJECT ); msg = 'Object' case default ; msg = 'Unknown' end select end function FPM_TARGET_NAME !> High-level wrapper to generate build target information subroutine targets_from_sources ( targets , model , prune , error ) !> The generated list of build targets type ( build_target_ptr ), intent ( out ), allocatable :: targets (:) !> The package model from which to construct the target list type ( fpm_model_t ), intent ( inout ), target :: model !> Enable tree-shaking/pruning of module dependencies logical , intent ( in ) :: prune !> Error structure type ( error_t ), intent ( out ), allocatable :: error call build_target_list ( targets , model ) call collect_exe_link_dependencies ( targets ) call resolve_module_dependencies ( targets , model % external_modules , error ) if ( allocated ( error )) return if ( prune ) then call prune_build_targets ( targets , root_package = model % package_name ) end if call resolve_target_linking ( targets , model ) end subroutine targets_from_sources !> Constructs a list of build targets from a list of source files !> !>### Source-target mapping !> !> One compiled object target (`FPM_TARGET_OBJECT`) is generated for each !> non-executable source file (`FPM_UNIT_MODULE`,`FPM_UNIT_SUBMODULE`, !> `FPM_UNIT_SUBPROGRAM`,`FPM_UNIT_CSOURCE`). !> !> If any source file has scope `FPM_SCOPE_LIB` (*i.e.* there are library sources) !> then the first target in the target list will be a library archive target !> (`FPM_TARGET_ARCHIVE`). The archive target will have a dependency on every !> compiled object target corresponding to a library source file. !> !> One compiled object target (`FPM_TARGET_OBJECT`) and one executable target (`FPM_TARGET_EXECUTABLE`) is !> generated for each exectuable source file (`FPM_UNIT_PROGRAM`). The exectuble target !> always has a dependency on the corresponding compiled object target. If there !> is a library, then the executable target has an additional dependency on the library !> archive target. !> subroutine build_target_list ( targets , model ) !> The generated list of build targets type ( build_target_ptr ), intent ( out ), allocatable :: targets (:) !> The package model from which to construct the target list type ( fpm_model_t ), intent ( inout ), target :: model integer :: i , j , n_source , exe_type character (:), allocatable :: exe_dir , compile_flags logical :: with_lib ! Initialize targets allocate ( targets ( 0 )) ! Check for empty build (e.g. header-only lib) n_source = sum ([( size ( model % packages ( j )% sources ), & j = 1 , size ( model % packages ))]) if ( n_source < 1 ) return with_lib = any ([(( model % packages ( j )% sources ( i )% unit_scope == FPM_SCOPE_LIB , & i = 1 , size ( model % packages ( j )% sources )), & j = 1 , size ( model % packages ))]) if ( with_lib ) call add_target ( targets , package = model % package_name , type = FPM_TARGET_ARCHIVE ,& output_name = join_path (& model % package_name , 'lib' // model % package_name // '.a' )) do j = 1 , size ( model % packages ) associate ( sources => model % packages ( j )% sources ) do i = 1 , size ( sources ) if (. not . model % include_tests ) then if ( sources ( i )% unit_scope == FPM_SCOPE_TEST ) cycle end if select case ( sources ( i )% unit_type ) case ( FPM_UNIT_MODULE , FPM_UNIT_SUBMODULE , FPM_UNIT_SUBPROGRAM , FPM_UNIT_CSOURCE ) call add_target ( targets , package = model % packages ( j )% name , source = sources ( i ), & type = merge ( FPM_TARGET_C_OBJECT , FPM_TARGET_OBJECT ,& sources ( i )% unit_type == FPM_UNIT_CSOURCE ), & output_name = get_object_name ( sources ( i )), & features = model % packages ( j )% features , & preprocess = model % packages ( j )% preprocess , & version = model % packages ( j )% version ) if ( with_lib . and . sources ( i )% unit_scope == FPM_SCOPE_LIB ) then ! Archive depends on object call add_dependency ( targets ( 1 )% ptr , targets ( size ( targets ))% ptr ) end if case ( FPM_UNIT_CPPSOURCE ) call add_target ( targets , package = model % packages ( j )% name , source = sources ( i ), & type = FPM_TARGET_CPP_OBJECT , & output_name = get_object_name ( sources ( i )), & preprocess = model % packages ( j )% preprocess , & version = model % packages ( j )% version ) if ( with_lib . and . sources ( i )% unit_scope == FPM_SCOPE_LIB ) then ! Archive depends on object call add_dependency ( targets ( 1 )% ptr , targets ( size ( targets ))% ptr ) end if !> Add stdc++ as a linker flag. If not already there. if (. not . ( \"stdc++\" . in . model % link_libraries )) then if ( get_os_type () == OS_MACOS ) then model % link_libraries = [ model % link_libraries , string_t ( \"c++\" )] else model % link_libraries = [ model % link_libraries , string_t ( \"stdc++\" )] end if end if case ( FPM_UNIT_PROGRAM ) if ( str_ends_with ( lower ( sources ( i )% file_name ), [ \".c\" ])) then exe_type = FPM_TARGET_C_OBJECT else if ( str_ends_with ( lower ( sources ( i )% file_name ), [ \".cpp\" , \".cc \" ])) then exe_type = FPM_TARGET_CPP_OBJECT else ! Default to a Fortran object exe_type = FPM_TARGET_OBJECT end if call add_target ( targets , package = model % packages ( j )% name , type = exe_type ,& output_name = get_object_name ( sources ( i )), & source = sources ( i ), & features = model % packages ( j )% features , & preprocess = model % packages ( j )% preprocess & ) if ( sources ( i )% unit_scope == FPM_SCOPE_APP ) then exe_dir = 'app' else if ( sources ( i )% unit_scope == FPM_SCOPE_EXAMPLE ) then exe_dir = 'example' else exe_dir = 'test' end if call add_target ( targets , package = model % packages ( j )% name , type = FPM_TARGET_EXECUTABLE ,& link_libraries = sources ( i )% link_libraries , & output_name = join_path ( exe_dir , get_exe_name_with_suffix ( sources ( i )))) associate ( target => targets ( size ( targets ))% ptr ) ! Linker-only flags are necessary on some compilers for codes with non-Fortran main select case ( exe_type ) case ( FPM_TARGET_C_OBJECT ) call model % compiler % get_main_flags ( \"c\" , compile_flags ) case ( FPM_TARGET_CPP_OBJECT ) call model % compiler % get_main_flags ( \"c++\" , compile_flags ) case default compile_flags = \"\" end select target % compile_flags = target % compile_flags // ' ' // compile_flags ! Executable depends on object call add_dependency ( target , targets ( size ( targets ) - 1 )% ptr ) if ( with_lib ) then ! Executable depends on library call add_dependency ( target , targets ( 1 )% ptr ) end if endassociate end select end do end associate end do contains function get_object_name ( source ) result ( object_file ) ! Generate object target path from source name and model params ! ! type ( srcfile_t ), intent ( in ) :: source character (:), allocatable :: object_file integer :: i character ( 1 ), parameter :: filesep = '/' object_file = canon_path ( source % file_name ) ! Convert any remaining directory separators to underscores i = index ( object_file , filesep ) do while ( i > 0 ) object_file ( i : i ) = '_' i = index ( object_file , filesep ) end do object_file = join_path ( model % package_name , object_file ) // '.o' end function get_object_name end subroutine build_target_list !> Add non-library non-module dependencies for executable targets !> !> Executable targets will link to any non-program non-module source files that !> are in the same directory or in a subdirectory. !> !> (Note: Fortran module dependencies are handled separately in !> `resolve_module_dependencies` and `resolve_target_linking`.) !> subroutine collect_exe_link_dependencies ( targets ) type ( build_target_ptr ), intent ( inout ) :: targets (:) integer :: i , j character (:), allocatable :: exe_source_dir ! Add non-module dependencies for executables do j = 1 , size ( targets ) if ( targets ( j )% ptr % target_type == FPM_TARGET_EXECUTABLE ) then do i = 1 , size ( targets ) if ( i == j ) cycle associate ( exe => targets ( j )% ptr , dep => targets ( i )% ptr ) exe_source_dir = dirname ( exe % dependencies ( 1 )% ptr % source % file_name ) if ( allocated ( dep % source )) then if ( dep % source % unit_scope /= FPM_SCOPE_LIB . and . & dep % source % unit_type /= FPM_UNIT_PROGRAM . and . & dep % source % unit_type /= FPM_UNIT_MODULE . and . & index ( dirname ( dep % source % file_name ), exe_source_dir ) == 1 ) then call add_dependency ( exe , dep ) end if end if end associate end do end if end do end subroutine collect_exe_link_dependencies !> Allocate a new target and append to target list subroutine add_target ( targets , package , type , output_name , source , link_libraries , & & features , preprocess , version ) type ( build_target_ptr ), allocatable , intent ( inout ) :: targets (:) character ( * ), intent ( in ) :: package integer , intent ( in ) :: type character ( * ), intent ( in ) :: output_name type ( srcfile_t ), intent ( in ), optional :: source type ( string_t ), intent ( in ), optional :: link_libraries (:) type ( fortran_features_t ), intent ( in ), optional :: features type ( preprocess_config_t ), intent ( in ), optional :: preprocess character ( * ), intent ( in ), optional :: version integer :: i type ( build_target_t ), pointer :: new_target if (. not . allocated ( targets )) allocate ( targets ( 0 )) ! Check for duplicate outputs do i = 1 , size ( targets ) if ( targets ( i )% ptr % output_name == output_name ) then write ( * , * ) 'Error while building target list: duplicate output object \"' ,& output_name , '\"' if ( present ( source )) write ( * , * ) ' Source file: \"' , source % file_name , '\"' call fpm_stop ( 1 , ' ' ) end if end do allocate ( new_target ) new_target % target_type = type new_target % output_name = output_name new_target % package_name = package if ( present ( source )) new_target % source = source if ( present ( link_libraries )) new_target % link_libraries = link_libraries if ( present ( features )) new_target % features = features if ( present ( preprocess )) then if ( allocated ( preprocess % macros )) new_target % macros = preprocess % macros endif if ( present ( version )) new_target % version = version allocate ( new_target % dependencies ( 0 )) targets = [ targets , build_target_ptr ( new_target )] end subroutine add_target !> Add pointer to dependeny in target%dependencies subroutine add_dependency ( target , dependency ) type ( build_target_t ), intent ( inout ) :: target type ( build_target_t ) , intent ( in ), target :: dependency target % dependencies = [ target % dependencies , build_target_ptr ( dependency )] end subroutine add_dependency !> Add dependencies to source-based targets (`FPM_TARGET_OBJECT`) !> based on any modules used by the corresponding source file. !> !>### Source file scoping !> !> Source files are assigned a scope of either `FPM_SCOPE_LIB`, !> `FPM_SCOPE_APP` or `FPM_SCOPE_TEST`. The scope controls which !> modules may be used by the source file: !> !> - Library sources (`FPM_SCOPE_LIB`) may only use modules !> also with library scope. This includes library modules !> from dependencies. !> !> - Executable sources (`FPM_SCOPE_APP`,`FPM_SCOPE_TEST`) may use !> library modules (including dependencies) as well as any modules !> corresponding to source files in the same directory or a !> subdirectory of the executable source file. !> !> @warning If a module used by a source file cannot be resolved to !> a source file in the package of the correct scope, then a __fatal error__ !> is returned by the procedure and model construction fails. !> subroutine resolve_module_dependencies ( targets , external_modules , error ) type ( build_target_ptr ), intent ( inout ), target :: targets (:) type ( string_t ), intent ( in ) :: external_modules (:) type ( error_t ), allocatable , intent ( out ) :: error type ( build_target_ptr ) :: dep integer :: i , j do i = 1 , size ( targets ) if (. not . allocated ( targets ( i )% ptr % source )) cycle do j = 1 , size ( targets ( i )% ptr % source % modules_used ) if ( targets ( i )% ptr % source % modules_used ( j )% s . in . targets ( i )% ptr % source % modules_provided ) then ! Dependency satisfied in same file, skip cycle end if if ( targets ( i )% ptr % source % modules_used ( j )% s . in . external_modules ) then ! Dependency satisfied in system-installed module cycle end if if ( any ( targets ( i )% ptr % source % unit_scope == & [ FPM_SCOPE_APP , FPM_SCOPE_EXAMPLE , FPM_SCOPE_TEST ])) then dep % ptr => & find_module_dependency ( targets , targets ( i )% ptr % source % modules_used ( j )% s , & include_dir = dirname ( targets ( i )% ptr % source % file_name )) else dep % ptr => & find_module_dependency ( targets , targets ( i )% ptr % source % modules_used ( j )% s ) end if if (. not . associated ( dep % ptr )) then call fatal_error ( error , & 'Unable to find source for module dependency: \"' // & targets ( i )% ptr % source % modules_used ( j )% s // & '\" used by \"' // targets ( i )% ptr % source % file_name // '\"' ) return end if call add_dependency ( targets ( i )% ptr , dep % ptr ) end do end do end subroutine resolve_module_dependencies function find_module_dependency ( targets , module_name , include_dir ) result ( target_ptr ) ! Find a module dependency in the library or a dependency library ! ! 'include_dir' specifies an allowable non-library search directory ! (Used for executable dependencies) ! type ( build_target_ptr ), intent ( in ), target :: targets (:) character ( * ), intent ( in ) :: module_name character ( * ), intent ( in ), optional :: include_dir type ( build_target_t ), pointer :: target_ptr integer :: k , l target_ptr => NULL () do k = 1 , size ( targets ) if (. not . allocated ( targets ( k )% ptr % source )) cycle do l = 1 , size ( targets ( k )% ptr % source % modules_provided ) if ( module_name == targets ( k )% ptr % source % modules_provided ( l )% s ) then select case ( targets ( k )% ptr % source % unit_scope ) case ( FPM_SCOPE_LIB , FPM_SCOPE_DEP ) target_ptr => targets ( k )% ptr exit case default if ( present ( include_dir )) then if ( index ( dirname ( targets ( k )% ptr % source % file_name ), include_dir ) == 1 ) then ! source file is within the include_dir or a subdirectory target_ptr => targets ( k )% ptr exit end if end if end select end if end do end do end function find_module_dependency !> Perform tree-shaking to remove unused module targets subroutine prune_build_targets ( targets , root_package ) !> Build target list to prune type ( build_target_ptr ), intent ( inout ), allocatable :: targets (:) !> Name of root package character ( * ), intent ( in ) :: root_package integer :: i , j , nexec type ( string_t ), allocatable :: modules_used (:) logical :: exclude_target ( size ( targets )) logical , allocatable :: exclude_from_archive (:) if ( size ( targets ) < 1 ) then return end if nexec = 0 allocate ( modules_used ( 0 )) ! Enumerate modules used by executables, non-module subprograms and their dependencies do i = 1 , size ( targets ) if ( targets ( i )% ptr % target_type == FPM_TARGET_EXECUTABLE ) then nexec = nexec + 1 call collect_used_modules ( targets ( i )% ptr ) elseif ( allocated ( targets ( i )% ptr % source )) then if ( targets ( i )% ptr % source % unit_type == FPM_UNIT_SUBPROGRAM ) then call collect_used_modules ( targets ( i )% ptr ) end if end if end do ! If there aren't any executables, then prune ! based on modules used in root package if ( nexec < 1 ) then do i = 1 , size ( targets ) if ( targets ( i )% ptr % package_name == root_package . and . & targets ( i )% ptr % target_type /= FPM_TARGET_ARCHIVE ) then call collect_used_modules ( targets ( i )% ptr ) end if end do end if call reset_target_flags ( targets ) exclude_target (:) = . false . ! Exclude purely module targets if they are not used anywhere do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( allocated ( target % source )) then if ( target % source % unit_type == FPM_UNIT_MODULE ) then exclude_target ( i ) = . true . target % skip = . true . do j = 1 , size ( target % source % modules_provided ) if ( target % source % modules_provided ( j )% s . in . modules_used ) then exclude_target ( i ) = . false . target % skip = . false . end if end do elseif ( target % source % unit_type == FPM_UNIT_SUBMODULE ) then ! Remove submodules if their parents are not used exclude_target ( i ) = . true . target % skip = . true . do j = 1 , size ( target % source % parent_modules ) if ( target % source % parent_modules ( j )% s . in . modules_used ) then exclude_target ( i ) = . false . target % skip = . false . end if end do end if end if ! (If there aren't any executables then we only prune modules from dependencies) if ( nexec < 1 . and . target % package_name == root_package ) then exclude_target ( i ) = . false . target % skip = . false . end if end associate end do targets = pack ( targets ,. not . exclude_target ) ! Remove unused targets from archive dependency list if ( targets ( 1 )% ptr % target_type == FPM_TARGET_ARCHIVE ) then associate ( archive => targets ( 1 )% ptr ) allocate ( exclude_from_archive ( size ( archive % dependencies ))) exclude_from_archive (:) = . false . do i = 1 , size ( archive % dependencies ) if ( archive % dependencies ( i )% ptr % skip ) then exclude_from_archive ( i ) = . true . end if end do archive % dependencies = pack ( archive % dependencies ,. not . exclude_from_archive ) end associate end if contains !> Recursively collect which modules are actually used recursive subroutine collect_used_modules ( target ) type ( build_target_t ), intent ( inout ) :: target integer :: j , k if ( target % touched ) then return else target % touched = . true . end if if ( allocated ( target % source )) then ! Add modules from this target and from any of it's children submodules do j = 1 , size ( target % source % modules_provided ) if (. not .( target % source % modules_provided ( j )% s . in . modules_used )) then modules_used = [ modules_used , target % source % modules_provided ( j )] end if ! Recurse into child submodules do k = 1 , size ( targets ) if ( allocated ( targets ( k )% ptr % source )) then if ( targets ( k )% ptr % source % unit_type == FPM_UNIT_SUBMODULE ) then if ( target % source % modules_provided ( j )% s . in . targets ( k )% ptr % source % parent_modules ) then call collect_used_modules ( targets ( k )% ptr ) end if end if end if end do end do end if ! Recurse into dependencies do j = 1 , size ( target % dependencies ) if ( target % dependencies ( j )% ptr % target_type /= FPM_TARGET_ARCHIVE ) then call collect_used_modules ( target % dependencies ( j )% ptr ) end if end do end subroutine collect_used_modules !> Reset target flags after recursive search subroutine reset_target_flags ( targets ) type ( build_target_ptr ), intent ( inout ) :: targets (:) integer :: i do i = 1 , size ( targets ) targets ( i )% ptr % touched = . false . end do end subroutine reset_target_flags end subroutine prune_build_targets !> Construct the linker flags string for each target !> `target%link_flags` includes non-library objects and library flags !> subroutine resolve_target_linking ( targets , model ) type ( build_target_ptr ), intent ( inout ), target :: targets (:) type ( fpm_model_t ), intent ( in ) :: model integer :: i character (:), allocatable :: global_link_flags , local_link_flags character (:), allocatable :: global_include_flags if ( size ( targets ) == 0 ) return global_link_flags = \"\" if ( allocated ( model % link_libraries )) then if ( size ( model % link_libraries ) > 0 ) then global_link_flags = model % compiler % enumerate_libraries ( global_link_flags , model % link_libraries ) end if end if allocate ( character ( 0 ) :: global_include_flags ) if ( allocated ( model % include_dirs )) then if ( size ( model % include_dirs ) > 0 ) then global_include_flags = global_include_flags // & & \" -I\" // string_cat ( model % include_dirs , \" -I\" ) end if end if do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) ! If the main program is a C/C++ one, some compilers require additional linking flags, see ! https://stackoverflow.com/questions/36221612/p3dfft-compilation-ifort-compiler-error-multiple-definiton-of-main ! In this case, compile_flags were already allocated if (. not . allocated ( target % compile_flags )) allocate ( character ( len = 0 ) :: target % compile_flags ) target % compile_flags = target % compile_flags // ' ' select case ( target % target_type ) case ( FPM_TARGET_C_OBJECT ) target % compile_flags = target % compile_flags // model % c_compile_flags case ( FPM_TARGET_CPP_OBJECT ) target % compile_flags = target % compile_flags // model % cxx_compile_flags case default target % compile_flags = target % compile_flags // model % fortran_compile_flags & & // get_feature_flags ( model % compiler , target % features ) end select !> Get macros as flags. target % compile_flags = target % compile_flags // get_macros ( model % compiler % id , & target % macros , & target % version ) if ( len ( global_include_flags ) > 0 ) then target % compile_flags = target % compile_flags // global_include_flags end if target % output_dir = get_output_dir ( model % build_prefix , target % compile_flags ) target % output_file = join_path ( target % output_dir , target % output_name ) target % output_log_file = join_path ( target % output_dir , target % output_name ) // '.log' end associate end do call add_include_build_dirs ( model , targets ) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) allocate ( target % link_objects ( 0 )) if ( target % target_type == FPM_TARGET_ARCHIVE ) then global_link_flags = target % output_file // global_link_flags call get_link_objects ( target % link_objects , target , is_exe = . false .) allocate ( character ( 0 ) :: target % link_flags ) else if ( target % target_type == FPM_TARGET_EXECUTABLE ) then call get_link_objects ( target % link_objects , target , is_exe = . true .) local_link_flags = \"\" if ( allocated ( model % link_flags )) local_link_flags = model % link_flags target % link_flags = model % link_flags // \" \" // string_cat ( target % link_objects , \" \" ) if ( allocated ( target % link_libraries )) then if ( size ( target % link_libraries ) > 0 ) then target % link_flags = model % compiler % enumerate_libraries ( target % link_flags , target % link_libraries ) local_link_flags = model % compiler % enumerate_libraries ( local_link_flags , target % link_libraries ) end if end if target % link_flags = target % link_flags // \" \" // global_link_flags target % output_dir = get_output_dir ( model % build_prefix , & & target % compile_flags // local_link_flags ) target % output_file = join_path ( target % output_dir , target % output_name ) target % output_log_file = join_path ( target % output_dir , target % output_name ) // '.log' end if end associate end do contains !> Wrapper to build link object list !> !> For libraries: just list dependency objects of lib target !> !> For executables: need to recursively discover non-library !> dependency objects. (i.e. modules in same dir as program) !> recursive subroutine get_link_objects ( link_objects , target , is_exe ) type ( string_t ), intent ( inout ), allocatable :: link_objects (:) type ( build_target_t ), intent ( in ) :: target logical , intent ( in ) :: is_exe integer :: i type ( string_t ) :: temp_str if (. not . allocated ( target % dependencies )) return do i = 1 , size ( target % dependencies ) associate ( dep => target % dependencies ( i )% ptr ) if (. not . allocated ( dep % source )) cycle ! Skip library dependencies for executable targets ! since the library archive will always be linked if ( is_exe . and .( dep % source % unit_scope == FPM_SCOPE_LIB )) cycle ! Skip if dependency object already listed if ( dep % output_file . in . link_objects ) cycle ! Add dependency object file to link object list temp_str % s = dep % output_file link_objects = [ link_objects , temp_str ] ! For executable objects, also need to include non-library ! dependencies from dependencies (recurse) if ( is_exe ) call get_link_objects ( link_objects , dep , is_exe = . true .) end associate end do end subroutine get_link_objects end subroutine resolve_target_linking subroutine add_include_build_dirs ( model , targets ) type ( fpm_model_t ), intent ( in ) :: model type ( build_target_ptr ), intent ( inout ), target :: targets (:) integer :: i type ( string_t ), allocatable :: build_dirs (:) type ( string_t ) :: temp allocate ( build_dirs ( 0 )) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( target % target_type /= FPM_TARGET_OBJECT ) cycle if ( target % output_dir . in . build_dirs ) cycle temp % s = target % output_dir build_dirs = [ build_dirs , temp ] end associate end do do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( target % target_type /= FPM_TARGET_OBJECT ) cycle target % compile_flags = target % compile_flags // & \" \" // model % compiler % get_module_flag ( target % output_dir ) // & \" -I\" // string_cat ( build_dirs , \" -I\" ) end associate end do end subroutine add_include_build_dirs function get_output_dir ( build_prefix , args ) result ( path ) character ( len =* ), intent ( in ) :: build_prefix character ( len =* ), intent ( in ) :: args character ( len = :), allocatable :: path character ( len = 16 ) :: build_hash write ( build_hash , '(z16.16)' ) fnv_1a ( args ) path = build_prefix // \"_\" // build_hash end function get_output_dir subroutine filter_library_targets ( targets , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , n n = 0 call resize ( list ) do i = 1 , size ( targets ) if ( targets ( i )% ptr % target_type == FPM_TARGET_ARCHIVE ) then if ( n >= size ( list )) call resize ( list ) n = n + 1 list ( n )% s = targets ( i )% ptr % output_file end if end do call resize ( list , n ) end subroutine filter_library_targets subroutine filter_executable_targets ( targets , scope , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) integer , intent ( in ) :: scope type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , n n = 0 call resize ( list ) do i = 1 , size ( targets ) if ( is_executable_target ( targets ( i )% ptr , scope )) then if ( n >= size ( list )) call resize ( list ) n = n + 1 list ( n )% s = targets ( i )% ptr % output_file end if end do call resize ( list , n ) end subroutine filter_executable_targets elemental function is_executable_target ( target_ptr , scope ) result ( is_exe ) class ( build_target_t ), intent ( in ) :: target_ptr integer , intent ( in ) :: scope logical :: is_exe is_exe = target_ptr % target_type == FPM_TARGET_EXECUTABLE . and . & allocated ( target_ptr % dependencies ) if ( is_exe ) then is_exe = target_ptr % dependencies ( 1 )% ptr % source % unit_scope == scope end if end function is_executable_target subroutine filter_modules ( targets , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , j , n n = 0 call resize ( list ) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if (. not . allocated ( target % source )) cycle if ( target % source % unit_type == FPM_UNIT_SUBMODULE ) cycle if ( n + size ( target % source % modules_provided ) >= size ( list )) call resize ( list ) do j = 1 , size ( target % source % modules_provided ) n = n + 1 list ( n )% s = join_path ( target % output_dir , & target % source % modules_provided ( j )% s ) end do end associate end do call resize ( list , n ) end subroutine filter_modules function get_feature_flags ( compiler , features ) result ( flags ) type ( compiler_t ), intent ( in ) :: compiler type ( fortran_features_t ), intent ( in ) :: features character (:), allocatable :: flags flags = \"\" if ( features % implicit_typing ) then flags = flags // compiler % get_feature_flag ( \"implicit-typing\" ) else flags = flags // compiler % get_feature_flag ( \"no-implicit-typing\" ) end if if ( features % implicit_external ) then flags = flags // compiler % get_feature_flag ( \"implicit-external\" ) else flags = flags // compiler % get_feature_flag ( \"no-implicit-external\" ) end if if ( allocated ( features % source_form )) then flags = flags // compiler % get_feature_flag ( features % source_form // \"-form\" ) end if end function get_feature_flags end module fpm_targets","tags":"","loc":"sourcefile/fpm_targets.f90.html"},{"title":"profiles.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for compiler flag profiles. !> !> A profiles table can currently have the following subtables: !> Profile names - any string, if omitted, flags are appended to all matching profiles !> Compiler - any from the following list, omitting it yields an error !> !> - \"gfortran\" !> - \"ifort\" !> - \"ifx\" !> - \"pgfortran\" !> - \"nvfortran\" !> - \"flang\" !> - \"caf\" !> - \"f95\" !> - \"lfortran\" !> - \"lfc\" !> - \"nagfor\" !> - \"crayftn\" !> - \"xlf90\" !> - \"ftn95\" !> !> OS - any from the following list, if omitted, the profile is used if and only !> if there is no profile perfectly matching the current configuration !> !> - \"linux\" !> - \"macos\" !> - \"windows\" !> - \"cygwin\" !> - \"solaris\" !> - \"freebsd\" !> - \"openbsd\" !> - \"unknown\" !> !> Each of the subtables currently supports the following fields: !>```toml !>[profiles.debug.gfortran.linux] !> flags=\"-Wall -g -Og\" !> c-flags=\"-g O1\" !> cxx-flags=\"-g O1\" !> link-time-flags=\"-xlinkopt\" !> files={\"hello_world.f90\"=\"-Wall -O3\"} !>``` !> module fpm_manifest_profile use fpm_error , only : error_t , syntax_error , fatal_error , fpm_stop use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , serializable_t , set_value , & set_string , add_table use fpm_strings , only : lower use fpm_environment , only : get_os_type , OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_WINDOWS , & OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD , OS_NAME use fpm_filesystem , only : join_path implicit none public :: profile_config_t , new_profile , new_profiles , get_default_profiles , & & info_profile , find_profile , DEFAULT_COMPILER !> Name of the default compiler character ( len =* ), parameter :: DEFAULT_COMPILER = 'gfortran' integer , parameter :: OS_ALL = - 1 character ( len = :), allocatable :: path !> Type storing file name - file scope compiler flags pairs type , extends ( serializable_t ) :: file_scope_flag !> Name of the file character ( len = :), allocatable :: file_name !> File scope flags character ( len = :), allocatable :: flags contains !> Serialization interface procedure :: serializable_is_same => file_scope_same procedure :: dump_to_toml => file_scope_dump procedure :: load_from_toml => file_scope_load end type file_scope_flag !> Configuration meta data for a profile type , extends ( serializable_t ) :: profile_config_t !> Name of the profile character ( len = :), allocatable :: profile_name !> Name of the compiler character ( len = :), allocatable :: compiler !> Value repesenting OS integer :: os_type = OS_ALL !> Fortran compiler flags character ( len = :), allocatable :: flags !> C compiler flags character ( len = :), allocatable :: c_flags !> C++ compiler flags character ( len = :), allocatable :: cxx_flags !> Link time compiler flags character ( len = :), allocatable :: link_time_flags !> File scope flags type ( file_scope_flag ), allocatable :: file_scope_flags (:) !> Is this profile one of the built-in ones? logical :: is_built_in = . false . contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => profile_same procedure :: dump_to_toml => profile_dump procedure :: load_from_toml => profile_load end type profile_config_t contains !> Construct a new profile configuration from a TOML data structure function new_profile ( profile_name , compiler , os_type , flags , c_flags , cxx_flags , & link_time_flags , file_scope_flags , is_built_in ) & & result ( profile ) !> Name of the profile character ( len =* ), intent ( in ) :: profile_name !> Name of the compiler character ( len =* ), intent ( in ) :: compiler !> Type of the OS integer , intent ( in ) :: os_type !> Fortran compiler flags character ( len =* ), optional , intent ( in ) :: flags !> C compiler flags character ( len =* ), optional , intent ( in ) :: c_flags !> C++ compiler flags character ( len =* ), optional , intent ( in ) :: cxx_flags !> Link time compiler flags character ( len =* ), optional , intent ( in ) :: link_time_flags !> File scope flags type ( file_scope_flag ), optional , intent ( in ) :: file_scope_flags (:) !> Is this profile one of the built-in ones? logical , optional , intent ( in ) :: is_built_in type ( profile_config_t ) :: profile profile % profile_name = profile_name profile % compiler = compiler profile % os_type = os_type if ( present ( flags )) then profile % flags = flags else profile % flags = \"\" end if if ( present ( c_flags )) then profile % c_flags = c_flags else profile % c_flags = \"\" end if if ( present ( cxx_flags )) then profile % cxx_flags = cxx_flags else profile % cxx_flags = \"\" end if if ( present ( link_time_flags )) then profile % link_time_flags = link_time_flags else profile % link_time_flags = \"\" end if if ( present ( file_scope_flags )) then profile % file_scope_flags = file_scope_flags end if if ( present ( is_built_in )) then profile % is_built_in = is_built_in else profile % is_built_in = . false . end if end function new_profile !> Check if compiler name is a valid compiler name subroutine validate_compiler_name ( compiler_name , is_valid ) !> Name of a compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> Boolean value of whether compiler_name is valid or not logical , intent ( out ) :: is_valid select case ( compiler_name ) case ( \"gfortran\" , \"ifort\" , \"ifx\" , \"pgfortran\" , \"nvfortran\" , \"flang\" , \"caf\" , & & \"f95\" , \"lfortran\" , \"lfc\" , \"nagfor\" , \"crayftn\" , \"xlf90\" , \"ftn95\" ) is_valid = . true . case default is_valid = . false . end select end subroutine validate_compiler_name !> Check if os_name is a valid name of a supported OS subroutine validate_os_name ( os_name , is_valid ) !> Name of an operating system character ( len = :), allocatable , intent ( in ) :: os_name !> Boolean value of whether os_name is valid or not logical , intent ( out ) :: is_valid select case ( os_name ) case ( \"linux\" , \"macos\" , \"windows\" , \"cygwin\" , \"solaris\" , \"freebsd\" , & & \"openbsd\" , \"unknown\" ) is_valid = . true . case default is_valid = . false . end select end subroutine validate_os_name !> Match os_type enum to a lowercase string with name of OS subroutine match_os_type ( os_name , os_type ) !> Name of operating system character ( len = :), allocatable , intent ( in ) :: os_name !> Enum representing type of OS integer , intent ( out ) :: os_type select case ( os_name ) case ( \"linux\" ); os_type = OS_LINUX case ( \"macos\" ); os_type = OS_MACOS case ( \"windows\" ); os_type = OS_WINDOWS case ( \"cygwin\" ); os_type = OS_CYGWIN case ( \"solaris\" ); os_type = OS_SOLARIS case ( \"freebsd\" ); os_type = OS_FREEBSD case ( \"openbsd\" ); os_type = OS_OPENBSD case ( \"all\" ); os_type = OS_ALL case default ; os_type = OS_UNKNOWN end select end subroutine match_os_type !> Match lowercase string with name of OS to os_type enum function os_type_name ( os_type ) !> Name of operating system character ( len = :), allocatable :: os_type_name !> Enum representing type of OS integer , intent ( in ) :: os_type select case ( os_type ) case ( OS_ALL ); os_type_name = \"all\" case default ; os_type_name = lower ( OS_NAME ( os_type )) end select end function os_type_name subroutine validate_profile_table ( profile_name , compiler_name , key_list , table , error , os_valid ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of keys in the table type ( toml_key ), allocatable , intent ( in ) :: key_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Was called with valid operating system logical , intent ( in ) :: os_valid character ( len = :), allocatable :: flags , c_flags , cxx_flags , link_time_flags , key_name , file_name , file_flags , err_message type ( toml_table ), pointer :: files type ( toml_key ), allocatable :: file_list (:) integer :: ikey , ifile , stat logical :: is_valid if ( size ( key_list ). ge . 1 ) then do ikey = 1 , size ( key_list ) key_name = key_list ( ikey )% key if ( key_name . eq . 'flags' ) then call get_value ( table , 'flags' , flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'c-flags' ) then call get_value ( table , 'c-flags' , c_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"c-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'cxx-flags' ) then call get_value ( table , 'cxx-flags' , cxx_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"cxx-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'link-time-flags' ) then call get_value ( table , 'link-time-flags' , link_time_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"link-time-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'files' ) then call get_value ( table , 'files' , files , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"files has to be a table\" ) return end if call files % get_keys ( file_list ) do ifile = 1 , size ( file_list ) file_name = file_list ( ifile )% key call get_value ( files , file_name , file_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"file scope flags has to be a key-value pair\" ) return end if end do else if (. not . os_valid ) then call validate_os_name ( key_name , is_valid ) err_message = \"Unexpected key \" // key_name // \" found in profile table \" // profile_name // \" \" // compiler_name // \".\" if (. not . is_valid ) call syntax_error ( error , err_message ) else err_message = \"Unexpected key \" // key_name // \" found in profile table \" // profile_name // \" \" // compiler_name // \".\" call syntax_error ( error , err_message ) end if end do end if if ( allocated ( error )) return end subroutine validate_profile_table !> Look for flags, c-flags, link-time-flags key-val pairs !> and files table in a given table and create new profiles subroutine get_flags ( profile_name , compiler_name , os_type , key_list , table , profiles , profindex , os_valid ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> OS type integer , intent ( in ) :: os_type !> List of keys in the table type ( toml_key ), allocatable , intent ( in ) :: key_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ) :: profiles (:) !> Index in the list of profiles integer , intent ( inout ) :: profindex !> Was called with valid operating system logical , intent ( in ) :: os_valid character ( len = :), allocatable :: flags , c_flags , cxx_flags , link_time_flags , key_name , file_name , file_flags , err_message type ( toml_table ), pointer :: files type ( toml_key ), allocatable :: file_list (:) type ( file_scope_flag ), allocatable :: file_scope_flags (:) integer :: ikey , ifile , stat logical :: is_valid call get_value ( table , 'flags' , flags ) call get_value ( table , 'c-flags' , c_flags ) call get_value ( table , 'cxx-flags' , cxx_flags ) call get_value ( table , 'link-time-flags' , link_time_flags ) call get_value ( table , 'files' , files ) if ( associated ( files )) then call files % get_keys ( file_list ) allocate ( file_scope_flags ( size ( file_list ))) do ifile = 1 , size ( file_list ) file_name = file_list ( ifile )% key call get_value ( files , file_name , file_flags ) associate ( cur_file => file_scope_flags ( ifile )) if (. not .( path . eq . \"\" )) file_name = join_path ( path , file_name ) cur_file % file_name = file_name cur_file % flags = file_flags end associate end do end if profiles ( profindex ) = new_profile ( profile_name , compiler_name , os_type , & & flags , c_flags , cxx_flags , link_time_flags , file_scope_flags ) profindex = profindex + 1 end subroutine get_flags !> Traverse operating system tables to obtain number of profiles subroutine traverse_oss_for_size ( profile_name , compiler_name , os_list , table , profiles_size , error ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of OSs in table with profile name and compiler name given type ( toml_key ), allocatable , intent ( in ) :: os_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Number of profiles in list of profiles integer , intent ( inout ) :: profiles_size type ( toml_key ), allocatable :: key_list (:) character ( len = :), allocatable :: os_name , l_os_name type ( toml_table ), pointer :: os_node integer :: ios , stat logical :: is_valid , key_val_added , is_key_val if ( size ( os_list ) < 1 ) return key_val_added = . false . do ios = 1 , size ( os_list ) os_name = os_list ( ios )% key call validate_os_name ( os_name , is_valid ) if ( is_valid ) then call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"os \" // os_name // \" has to be a table\" ) return end if call os_node % get_keys ( key_list ) profiles_size = profiles_size + 1 call validate_profile_table ( profile_name , compiler_name , key_list , os_node , error , . true .) else ! Not lowercase OS name l_os_name = lower ( os_name ) call validate_os_name ( l_os_name , is_valid ) if ( is_valid ) then call fatal_error ( error , '*traverse_oss*:Error: Name of the operating system must be a lowercase string.' ) end if if ( allocated ( error )) return ! Missing OS name is_key_val = . false . os_name = os_list ( ios )% key call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then is_key_val = . true . end if os_node => table if ( is_key_val . and .. not . key_val_added ) then key_val_added = . true . is_key_val = . false . profiles_size = profiles_size + 1 else if (. not . is_key_val ) then profiles_size = profiles_size + 1 end if call validate_profile_table ( profile_name , compiler_name , os_list , os_node , error , . false .) end if end do end subroutine traverse_oss_for_size !> Traverse operating system tables to obtain profiles subroutine traverse_oss ( profile_name , compiler_name , os_list , table , profiles , profindex , error ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of OSs in table with profile name and compiler name given type ( toml_key ), allocatable , intent ( in ) :: os_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ) :: profiles (:) !> Index in the list of profiles integer , intent ( inout ) :: profindex type ( toml_key ), allocatable :: key_list (:) character ( len = :), allocatable :: os_name , l_os_name type ( toml_table ), pointer :: os_node integer :: ios , stat , os_type logical :: is_valid , is_key_val if ( size ( os_list ) < 1 ) return do ios = 1 , size ( os_list ) os_name = os_list ( ios )% key call validate_os_name ( os_name , is_valid ) if ( is_valid ) then call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"os \" // os_name // \" has to be a table\" ) return end if call os_node % get_keys ( key_list ) call match_os_type ( os_name , os_type ) call get_flags ( profile_name , compiler_name , os_type , key_list , os_node , profiles , profindex , . true .) else ! Not lowercase OS name l_os_name = lower ( os_name ) call validate_os_name ( l_os_name , is_valid ) if ( is_valid ) then call fatal_error ( error , '*traverse_oss*:Error: Name of the operating system must be a lowercase string.' ) end if if ( allocated ( error )) return ! Missing OS name is_key_val = . false . os_name = os_list ( ios )% key call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then is_key_val = . true . end if os_node => table os_type = OS_ALL call get_flags ( profile_name , compiler_name , os_type , os_list , os_node , profiles , profindex , . false .) end if end do end subroutine traverse_oss !> Traverse compiler tables subroutine traverse_compilers ( profile_name , comp_list , table , error , profiles_size , profiles , profindex ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> List of OSs in table with profile name given type ( toml_key ), allocatable , intent ( in ) :: comp_list (:) !> Table containing compiler tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Number of profiles in list of profiles integer , intent ( inout ), optional :: profiles_size !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ), optional :: profiles (:) !> Index in the list of profiles integer , intent ( inout ), optional :: profindex character ( len = :), allocatable :: compiler_name type ( toml_table ), pointer :: comp_node type ( toml_key ), allocatable :: os_list (:) integer :: icomp , stat logical :: is_valid if ( size ( comp_list ) < 1 ) return do icomp = 1 , size ( comp_list ) call validate_compiler_name ( comp_list ( icomp )% key , is_valid ) if ( is_valid ) then compiler_name = comp_list ( icomp )% key call get_value ( table , compiler_name , comp_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Compiler \" // comp_list ( icomp )% key // \" must be a table entry\" ) exit end if call comp_node % get_keys ( os_list ) if ( present ( profiles_size )) then call traverse_oss_for_size ( profile_name , compiler_name , os_list , comp_node , profiles_size , error ) if ( allocated ( error )) return else if (. not .( present ( profiles ). and . present ( profindex ))) then call fatal_error ( error , \"Both profiles and profindex have to be present\" ) return end if call traverse_oss ( profile_name , compiler_name , os_list , comp_node , & & profiles , profindex , error ) if ( allocated ( error )) return end if else call fatal_error ( error , '*traverse_compilers*:Error: Compiler name not specified or invalid.' ) end if end do end subroutine traverse_compilers !> Construct new profiles array from a TOML data structure subroutine new_profiles ( profiles , table , error ) !> Instance of the dependency configuration type ( profile_config_t ), allocatable , intent ( out ) :: profiles (:) !> Instance of the TOML data structure type ( toml_table ), target , intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: prof_node type ( toml_key ), allocatable :: prof_list (:) type ( toml_key ), allocatable :: comp_list (:) type ( toml_key ), allocatable :: os_list (:) character ( len = :), allocatable :: profile_name , compiler_name integer :: profiles_size , iprof , stat , profindex logical :: is_valid type ( profile_config_t ), allocatable :: default_profiles (:) path = '' default_profiles = get_default_profiles ( error ) if ( allocated ( error )) return call table % get_keys ( prof_list ) if ( size ( prof_list ) < 1 ) return profiles_size = 0 do iprof = 1 , size ( prof_list ) profile_name = prof_list ( iprof )% key call validate_compiler_name ( profile_name , is_valid ) if ( is_valid ) then profile_name = \"all\" comp_list = prof_list ( iprof : iprof ) prof_node => table call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles_size = profiles_size ) if ( allocated ( error )) return else call validate_os_name ( profile_name , is_valid ) if ( is_valid ) then os_list = prof_list ( iprof : iprof ) profile_name = 'all' compiler_name = DEFAULT_COMPILER call traverse_oss_for_size ( profile_name , compiler_name , os_list , table , profiles_size , error ) if ( allocated ( error )) return else call get_value ( table , profile_name , prof_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Profile \" // prof_list ( iprof )% key // \" must be a table entry\" ) exit end if call prof_node % get_keys ( comp_list ) call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles_size = profiles_size ) if ( allocated ( error )) return end if end if end do profiles_size = profiles_size + size ( default_profiles ) allocate ( profiles ( profiles_size )) do profindex = 1 , size ( default_profiles ) profiles ( profindex ) = default_profiles ( profindex ) end do do iprof = 1 , size ( prof_list ) profile_name = prof_list ( iprof )% key call validate_compiler_name ( profile_name , is_valid ) if ( is_valid ) then profile_name = \"all\" comp_list = prof_list ( iprof : iprof ) prof_node => table call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles = profiles , profindex = profindex ) if ( allocated ( error )) return else call validate_os_name ( profile_name , is_valid ) if ( is_valid ) then os_list = prof_list ( iprof : iprof ) profile_name = 'all' compiler_name = DEFAULT_COMPILER prof_node => table call traverse_oss ( profile_name , compiler_name , os_list , prof_node , profiles , profindex , error ) if ( allocated ( error )) return else call get_value ( table , profile_name , prof_node , stat = stat ) call prof_node % get_keys ( comp_list ) call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles = profiles , profindex = profindex ) if ( allocated ( error )) return end if end if end do ! Apply profiles with profile name 'all' to matching profiles do iprof = 1 , size ( profiles ) if ( profiles ( iprof )% profile_name . eq . 'all' ) then do profindex = 1 , size ( profiles ) if (. not .( profiles ( profindex )% profile_name . eq . 'all' ) & & . and .( profiles ( profindex )% compiler . eq . profiles ( iprof )% compiler ) & & . and .( profiles ( profindex )% os_type . eq . profiles ( iprof )% os_type )) then profiles ( profindex )% flags = profiles ( profindex )% flags // & & \" \" // profiles ( iprof )% flags profiles ( profindex )% c_flags = profiles ( profindex )% c_flags // & & \" \" // profiles ( iprof )% c_flags profiles ( profindex )% cxx_flags = profiles ( profindex )% cxx_flags // & & \" \" // profiles ( iprof )% cxx_flags profiles ( profindex )% link_time_flags = profiles ( profindex )% link_time_flags // & & \" \" // profiles ( iprof )% link_time_flags end if end do end if end do end subroutine new_profiles !> Construct an array of built-in profiles function get_default_profiles ( error ) result ( default_profiles ) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( profile_config_t ), allocatable :: default_profiles (:) default_profiles = [ & & new_profile ( 'release' , & & 'caf' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -funroll-loops' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'gfortran' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -funroll-loops -fcoarray=single' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'f95' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'nvfortran' , & & OS_ALL , & & flags = ' -Mbackslash' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifort' , & & OS_ALL , & & flags = ' -fp-model precise -pc64 -align all -error-limit 1 -reentrancy& & threaded -nogen-interfaces -assume byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifort' , & & OS_WINDOWS , & & flags = ' /fp:precise /align:all /error-limit:1 /reentrancy:threaded& & /nogen-interfaces /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifx' , & & OS_ALL , & & flags = ' -fp-model=precise -pc64 -align all -error-limit 1 -reentrancy& & threaded -nogen-interfaces -assume byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /fp:precise /align:all /error-limit:1 /reentrancy:threaded& & /nogen-interfaces /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'nagfor' , & & OS_ALL , & & flags = ' -O4 -coarray=single -PIC' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'lfortran' , & & OS_ALL , & & flags = ' flag_lfortran_opt' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'caf' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -fbacktrace' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'gfortran' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -fbacktrace -fcoarray=single' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'f95' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -Wno-maybe-uninitialized -Wno-uninitialized -fbacktrace' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'nvfortran' , & & OS_ALL , & & flags = ' -Minform=inform -Mbackslash -g -Mbounds -Mchkptr -Mchkstk -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifort' , & & OS_ALL , & & flags = ' -warn all -check all -error-limit 1 -O0 -g -assume byterecl -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifort' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1& & /Od /Z7 /assume:byterecl /traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_ALL , & & flags = ' -warn all -check all -error-limit 1 -O0 -g -assume byterecl -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1 /Od /Z7 /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1 /Od /Z7 /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'lfortran' , & & OS_ALL , & & flags = '' , & & is_built_in = . true .) & &] end function get_default_profiles !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the profile configuration class ( profile_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if write ( unit , fmt ) \"Profile\" if ( allocated ( self % profile_name )) then write ( unit , fmt ) \"- profile name\" , self % profile_name end if if ( allocated ( self % compiler )) then write ( unit , fmt ) \"- compiler\" , self % compiler end if write ( unit , fmt ) \"- os\" , os_type_name ( self % os_type ) if ( allocated ( self % flags )) then write ( unit , fmt ) \"- compiler flags\" , self % flags end if end subroutine info !> Print a representation of profile_config_t function info_profile ( profile ) result ( s ) !> Profile to be represented type ( profile_config_t ), intent ( in ) :: profile !> String representation of given profile character (:), allocatable :: s integer :: i s = \"profile_config_t(\" s = s // 'profile_name=\"' // profile % profile_name // '\"' s = s // ', compiler=\"' // profile % compiler // '\"' s = s // \", os_type=\" select case ( profile % os_type ) case ( OS_UNKNOWN ) s = s // \"OS_UNKNOWN\" case ( OS_LINUX ) s = s // \"OS_LINUX\" case ( OS_MACOS ) s = s // \"OS_MACOS\" case ( OS_WINDOWS ) s = s // \"OS_WINDOWS\" case ( OS_CYGWIN ) s = s // \"OS_CYGWIN\" case ( OS_SOLARIS ) s = s // \"OS_SOLARIS\" case ( OS_FREEBSD ) s = s // \"OS_FREEBSD\" case ( OS_OPENBSD ) s = s // \"OS_OPENBSD\" case ( OS_ALL ) s = s // \"OS_ALL\" case default s = s // \"INVALID\" end select if ( allocated ( profile % flags )) s = s // ', flags=\"' // profile % flags // '\"' if ( allocated ( profile % c_flags )) s = s // ', c_flags=\"' // profile % c_flags // '\"' if ( allocated ( profile % cxx_flags )) s = s // ', cxx_flags=\"' // profile % cxx_flags // '\"' if ( allocated ( profile % link_time_flags )) s = s // ', link_time_flags=\"' // profile % link_time_flags // '\"' if ( allocated ( profile % file_scope_flags )) then do i = 1 , size ( profile % file_scope_flags ) s = s // ', flags for ' // profile % file_scope_flags ( i )% file_name // & & ' =\"' // profile % file_scope_flags ( i )% flags // '\"' end do end if s = s // \")\" end function info_profile !> Look for profile with given configuration in array profiles subroutine find_profile ( profiles , profile_name , compiler , os_type , found_matching , chosen_profile ) !> Array of profiles type ( profile_config_t ), allocatable , intent ( in ) :: profiles (:) !> Name of profile character (:), allocatable , intent ( in ) :: profile_name !> Name of compiler character (:), allocatable , intent ( in ) :: compiler !> Type of operating system (enum) integer , intent ( in ) :: os_type !> Boolean value containing true if matching profile was found logical , intent ( out ) :: found_matching !> Last matching profile in the profiles array type ( profile_config_t ), intent ( out ) :: chosen_profile character (:), allocatable :: curr_profile_name character (:), allocatable :: curr_compiler integer :: curr_os integer :: i , priority , curr_priority found_matching = . false . if ( size ( profiles ) < 1 ) return ! Try to find profile with matching OS type do i = 1 , size ( profiles ) curr_profile_name = profiles ( i )% profile_name curr_compiler = profiles ( i )% compiler curr_os = profiles ( i )% os_type if ( curr_profile_name . eq . profile_name ) then if ( curr_compiler . eq . compiler ) then if ( curr_os . eq . os_type ) then chosen_profile = profiles ( i ) found_matching = . true . end if end if end if end do ! Try to find profile with OS type 'all' if (. not . found_matching ) then do i = 1 , size ( profiles ) curr_profile_name = profiles ( i )% profile_name curr_compiler = profiles ( i )% compiler curr_os = profiles ( i )% os_type if ( curr_profile_name . eq . profile_name ) then if ( curr_compiler . eq . compiler ) then if ( curr_os . eq . OS_ALL ) then chosen_profile = profiles ( i ) found_matching = . true . end if end if end if end do end if end subroutine find_profile logical function file_scope_same ( this , that ) class ( file_scope_flag ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that file_scope_same = . false . select type ( other => that ) type is ( file_scope_flag ) if ( allocated ( this % file_name ). neqv . allocated ( other % file_name )) return if ( allocated ( this % file_name )) then if (. not .( this % file_name == other % file_name )) return endif if ( allocated ( this % flags ). neqv . allocated ( other % flags )) return if ( allocated ( this % flags )) then if (. not .( this % flags == other % flags )) return endif class default ! Not the same type return end select !> All checks passed! file_scope_same = . true . end function file_scope_same !> Dump to toml table subroutine file_scope_dump ( self , table , error ) !> Instance of the serializable object class ( file_scope_flag ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_string ( table , \"file-name\" , self % file_name , error ) if ( allocated ( error )) return call set_string ( table , \"flags\" , self % flags , error ) if ( allocated ( error )) return end subroutine file_scope_dump !> Read from toml table (no checks made at this stage) subroutine file_scope_load ( self , table , error ) !> Instance of the serializable object class ( file_scope_flag ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"file-name\" , self % file_name ) call get_value ( table , \"flags\" , self % flags ) end subroutine file_scope_load logical function profile_same ( this , that ) class ( profile_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii profile_same = . false . select type ( other => that ) type is ( profile_config_t ) if ( allocated ( this % profile_name ). neqv . allocated ( other % profile_name )) return if ( allocated ( this % profile_name )) then if (. not .( this % profile_name == other % profile_name )) return endif if ( allocated ( this % compiler ). neqv . allocated ( other % compiler )) return if ( allocated ( this % compiler )) then if (. not .( this % compiler == other % compiler )) return endif if ( this % os_type /= other % os_type ) return if ( allocated ( this % flags ). neqv . allocated ( other % flags )) return if ( allocated ( this % flags )) then if (. not .( this % flags == other % flags )) return endif if ( allocated ( this % c_flags ). neqv . allocated ( other % c_flags )) return if ( allocated ( this % c_flags )) then if (. not .( this % c_flags == other % c_flags )) return endif if ( allocated ( this % cxx_flags ). neqv . allocated ( other % cxx_flags )) return if ( allocated ( this % cxx_flags )) then if (. not .( this % cxx_flags == other % cxx_flags )) return endif if ( allocated ( this % link_time_flags ). neqv . allocated ( other % link_time_flags )) return if ( allocated ( this % link_time_flags )) then if (. not .( this % link_time_flags == other % link_time_flags )) return endif if ( allocated ( this % file_scope_flags ). neqv . allocated ( other % file_scope_flags )) return if ( allocated ( this % file_scope_flags )) then if (. not . size ( this % file_scope_flags ) == size ( other % file_scope_flags )) return do ii = 1 , size ( this % file_scope_flags ) print * , 'check ii-th file scope: ' , ii if (. not . this % file_scope_flags ( ii ) == other % file_scope_flags ( ii )) return end do endif if ( this % is_built_in . neqv . other % is_built_in ) return class default ! Not the same type return end select !> All checks passed! profile_same = . true . end function profile_same !> Dump to toml table subroutine profile_dump ( self , table , error ) !> Instance of the serializable object class ( profile_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: ierr , ii type ( toml_table ), pointer :: ptr_deps , ptr character ( len = 30 ) :: unnamed call set_string ( table , \"profile-name\" , self % profile_name , error ) if ( allocated ( error )) return call set_string ( table , \"compiler\" , self % compiler , error ) if ( allocated ( error )) return call set_string ( table , \"os-type\" , os_type_name ( self % os_type ), error , 'profile_config_t' ) if ( allocated ( error )) return call set_string ( table , \"flags\" , self % flags , error ) if ( allocated ( error )) return call set_string ( table , \"c-flags\" , self % c_flags , error ) if ( allocated ( error )) return call set_string ( table , \"cxx-flags\" , self % cxx_flags , error ) if ( allocated ( error )) return call set_string ( table , \"link-time-flags\" , self % link_time_flags , error ) if ( allocated ( error )) return if ( allocated ( self % file_scope_flags )) then ! Create dependency table call add_table ( table , \"file-scope-flags\" , ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , \"profile_config_t cannot create file scope table \" ) return end if do ii = 1 , size ( self % file_scope_flags ) associate ( dep => self % file_scope_flags ( ii )) !> Because files need a name, fallback if this has no name if ( len_trim ( dep % file_name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_deps , trim ( unnamed ), ptr ) else call add_table ( ptr_deps , dep % file_name , ptr ) end if if (. not . associated ( ptr )) then call fatal_error ( error , \"profile_config_t cannot create entry for file \" // dep % file_name ) return end if call dep % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do endif call set_value ( table , \"is-built-in\" , self % is_built_in , error , 'profile_config_t' ) if ( allocated ( error )) return 1 format ( 'UNNAMED_FILE_' , i0 ) end subroutine profile_dump !> Read from toml table (no checks made at this stage) subroutine profile_load ( self , table , error ) !> Instance of the serializable object class ( profile_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: flag integer :: ii , jj type ( toml_table ), pointer :: ptr_dep , ptr type ( toml_key ), allocatable :: keys (:), dep_keys (:) call table % get_keys ( keys ) call get_value ( table , \"profile-name\" , self % profile_name ) call get_value ( table , \"compiler\" , self % compiler ) call get_value ( table , \"os-type\" , flag ) call match_os_type ( flag , self % os_type ) call get_value ( table , \"flags\" , self % flags ) call get_value ( table , \"c-flags\" , self % c_flags ) call get_value ( table , \"cxx-flags\" , self % cxx_flags ) call get_value ( table , \"link-time-flags\" , self % link_time_flags ) call get_value ( table , \"is-built-in\" , self % is_built_in , error , 'profile_config_t' ) if ( allocated ( error )) return if ( allocated ( self % file_scope_flags )) deallocate ( self % file_scope_flags ) sub_deps : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"file-scope-flags\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'profile_config_t: error retrieving file_scope_flags table' ) return end if !> Read all packages call ptr % get_keys ( dep_keys ) allocate ( self % file_scope_flags ( size ( dep_keys ))) do jj = 1 , size ( dep_keys ) call get_value ( ptr , dep_keys ( jj ), ptr_dep ) call self % file_scope_flags ( jj )% load_from_toml ( ptr_dep , error ) if ( allocated ( error )) return end do end select end do sub_deps end subroutine profile_load end module fpm_manifest_profile","tags":"","loc":"sourcefile/profiles.f90.html"},{"title":"fpm_environment.f90 – Fortran-lang/fpm","text":"Source Code !> This module contains procedures that interact with the programming environment. !! !! * [get_os_type] -- Determine the OS type !! * [get_env] -- return the value of an environment variable module fpm_environment use , intrinsic :: iso_fortran_env , only : stdin => input_unit , & & stdout => output_unit , & & stderr => error_unit use , intrinsic :: iso_c_binding , only : c_char , c_int , c_null_char use fpm_error , only : fpm_stop implicit none private public :: get_os_type public :: os_is_unix public :: get_env public :: set_env public :: delete_env public :: get_command_arguments_quoted public :: separator public :: OS_NAME integer , parameter , public :: OS_UNKNOWN = 0 integer , parameter , public :: OS_LINUX = 1 integer , parameter , public :: OS_MACOS = 2 integer , parameter , public :: OS_WINDOWS = 3 integer , parameter , public :: OS_CYGWIN = 4 integer , parameter , public :: OS_SOLARIS = 5 integer , parameter , public :: OS_FREEBSD = 6 integer , parameter , public :: OS_OPENBSD = 7 contains !> Return string describing the OS type flag pure function OS_NAME ( os ) integer , intent ( in ) :: os character ( len = :), allocatable :: OS_NAME select case ( os ) case ( OS_LINUX ); OS_NAME = \"Linux\" case ( OS_MACOS ); OS_NAME = \"macOS\" case ( OS_WINDOWS ); OS_NAME = \"Windows\" case ( OS_CYGWIN ); OS_NAME = \"Cygwin\" case ( OS_SOLARIS ); OS_NAME = \"Solaris\" case ( OS_FREEBSD ); OS_NAME = \"FreeBSD\" case ( OS_OPENBSD ); OS_NAME = \"OpenBSD\" case ( OS_UNKNOWN ); OS_NAME = \"Unknown\" case default ; OS_NAME = \"UNKNOWN\" end select end function OS_NAME !> Determine the OS type integer function get_os_type () result ( r ) !! !! Returns one of OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, OS_CYGWIN, !! OS_SOLARIS, OS_FREEBSD, OS_OPENBSD. !! !! At first, the environment variable `OS` is checked, which is usually !! found on Windows. Then, `OSTYPE` is read in and compared with common !! names. If this fails too, check the existence of files that can be !! found on specific system types only. !! !! Returns OS_UNKNOWN if the operating system cannot be determined. character ( len = 255 ) :: val integer :: length , rc logical :: file_exists logical , save :: first_run = . true . integer , save :: ret = OS_UNKNOWN !$omp threadprivate(ret, first_run) if (. not . first_run ) then r = ret return end if first_run = . false . r = OS_UNKNOWN ! Check environment variable `OSTYPE`. call get_environment_variable ( 'OSTYPE' , val , length , rc ) if ( rc == 0 . and . length > 0 ) then ! Linux if ( index ( val , 'linux' ) > 0 ) then r = OS_LINUX ret = r return end if ! macOS if ( index ( val , 'darwin' ) > 0 ) then r = OS_MACOS ret = r return end if ! Windows, MSYS, MinGW, Git Bash if ( index ( val , 'win' ) > 0 . or . index ( val , 'msys' ) > 0 ) then r = OS_WINDOWS ret = r return end if ! Cygwin if ( index ( val , 'cygwin' ) > 0 ) then r = OS_CYGWIN ret = r return end if ! Solaris, OpenIndiana, ... if ( index ( val , 'SunOS' ) > 0 . or . index ( val , 'solaris' ) > 0 ) then r = OS_SOLARIS ret = r return end if ! FreeBSD if ( index ( val , 'FreeBSD' ) > 0 . or . index ( val , 'freebsd' ) > 0 ) then r = OS_FREEBSD ret = r return end if ! OpenBSD if ( index ( val , 'OpenBSD' ) > 0 . or . index ( val , 'openbsd' ) > 0 ) then r = OS_OPENBSD ret = r return end if end if ! Check environment variable `OS`. call get_environment_variable ( 'OS' , val , length , rc ) if ( rc == 0 . and . length > 0 . and . index ( val , 'Windows_NT' ) > 0 ) then r = OS_WINDOWS ret = r return end if ! Linux inquire ( file = '/etc/os-release' , exist = file_exists ) if ( file_exists ) then r = OS_LINUX ret = r return end if ! macOS inquire ( file = '/usr/bin/sw_vers' , exist = file_exists ) if ( file_exists ) then r = OS_MACOS ret = r return end if ! FreeBSD inquire ( file = '/bin/freebsd-version' , exist = file_exists ) if ( file_exists ) then r = OS_FREEBSD ret = r return end if end function get_os_type !> Compare the output of [[get_os_type]] or the optional !! passed INTEGER value to the value for OS_WINDOWS !! and return .TRUE. if they match and .FALSE. otherwise logical function os_is_unix ( os ) integer , intent ( in ), optional :: os integer :: build_os if ( present ( os )) then build_os = os else build_os = get_os_type () end if os_is_unix = build_os /= OS_WINDOWS end function os_is_unix !> get named environment variable value. It it is blank or !! not set return the optional default value function get_env ( NAME , DEFAULT ) result ( VALUE ) implicit none !> name of environment variable to get the value of character ( len =* ), intent ( in ) :: NAME !> default value to return if the requested value is undefined or blank character ( len =* ), intent ( in ), optional :: DEFAULT !> the returned value character ( len = :), allocatable :: VALUE integer :: howbig integer :: stat integer :: length ! get length required to hold value length = 0 if ( NAME /= '' ) then call get_environment_variable ( NAME , length = howbig , status = stat , trim_name = . true .) select case ( stat ) case ( 1 ) !*!print *, NAME, \" is not defined in the environment. Strange...\" VALUE = '' case ( 2 ) !*!print *, \"This processor doesn't support environment variables. Boooh!\" VALUE = '' case default ! make string to hold value of sufficient size allocate ( character ( len = max ( howbig , 1 )) :: VALUE ) ! get value call get_environment_variable ( NAME , VALUE , status = stat , trim_name = . true .) if ( stat /= 0 ) VALUE = '' end select else VALUE = '' endif if ( VALUE == '' . and . present ( DEFAULT )) VALUE = DEFAULT end function get_env function get_command_arguments_quoted () result ( args ) character ( len = :), allocatable :: args character ( len = :), allocatable :: arg character ( len = 1 ) :: quote integer :: ilength , istatus , i ilength = 0 args = '' quote = merge ( '\"' , \"'\" , separator () == '\\') do i=2,command_argument_count() ! look at all arguments after subcommand call get_command_argument(number=i,length=ilength,status=istatus) if(istatus /= 0) then write(stderr,' ( * ( g0 , 1 x )) ')' < ERROR >* get_command_arguments_stack * error obtaining argument ',i exit else if(allocated(arg))deallocate(arg) allocate(character(len=ilength) :: arg) call get_command_argument(number=i,value=arg,length=ilength,status=istatus) if(istatus /= 0) then write(stderr,' ( * ( g0 , 1 x )) ')' < ERROR >* get_command_arguments_stack * error obtaining argument ',i exit elseif(ilength>0)then if(index(arg//' ',' - ')/=1)then args=args//quote//arg//quote//' ' elseif(index(arg,' ')/=0)then args=args//quote//arg//quote//' ' else args=args//arg//' ' endif else args=args//repeat(quote,2)//' ' endif endif enddo end function get_command_arguments_quoted function separator() result(sep) !> !!##NAME !! separator(3f) - [M_io:ENVIRONMENT] try to determine pathname directory separator character !! (LICENSE:PD) !! !!##SYNOPSIS !! !! function separator() result(sep) !! !! character(len=1) :: sep !! !!##DESCRIPTION !! First using the name the program was invoked with, then the name !! returned by an INQUIRE(3f) of that name, then \".\\NAME\" and \"./NAME\" !! try to determine the separator character used to separate directory !! names from file basenames. !! !! If a slash or backslash is not found in the name, the environment !! variable PATH is examined first for a backslash, then a slash. !! !! Can be very system dependent. If the queries fail the default returned !! is \"/\". !! !!##EXAMPLE !! !! sample usage !! !! program demo_separator !! use M_io, only : separator !! implicit none !! write(*,*)' separator = ',separator() !! end program demo_separator ! use the pathname returned as arg0 to determine pathname separator implicit none character(len=:),allocatable :: arg0 integer :: arg0_length integer :: istat logical :: existing character(len=1) :: sep !*ifort_bug*!character(len=1),save :: sep_cache=' ' character(len=4096) :: name character(len=:),allocatable :: fname !*ifort_bug*! if(sep_cache/=' ')then ! use cached value. NOTE: A parallel code might theoretically use multiple OS !*ifort_bug*! sep=sep_cache !*ifort_bug*! return !*ifort_bug*! endif arg0_length=0 name=' ' call get_command_argument(0,length=arg0_length,status=istat) if(allocated(arg0))deallocate(arg0) allocate(character(len=arg0_length) :: arg0) call get_command_argument(0,arg0,status=istat) ! check argument name if(index(arg0,' \\ ')/=0)then sep=' \\ ' elseif(index(arg0,' / ')/=0)then sep=' / ' else ! try name returned by INQUIRE(3f) existing=.false. name=' ' inquire(file=arg0,iostat=istat,exist=existing,name=name) if(index(name,' \\ ')/=0)then sep=' \\ ' elseif(index(name,' / ')/=0)then sep=' / ' else ! well, try some common syntax and assume in current directory fname=' . \\ '//arg0 inquire(file=fname,iostat=istat,exist=existing) if(existing)then sep=' \\ ' else fname=' . / '//arg0 inquire(file=fname,iostat=istat,exist=existing) if(existing)then sep=' / ' else ! check environment variable PATH sep=merge(' \\ ',' / ',index(get_env(' PATH '),' \\ ')/=0) !*!write(*,*)' < WARNING > unknown system directory path separator ' endif endif endif endif !*ifort_bug*!sep_cache=sep end function separator !> Set an environment variable for the current environment using the C standard library logical function set_env ( name , value , overwrite ) !> Variable name character ( * ), intent ( in ) :: name !> Variable value character ( * ), intent ( in ) :: value !> Should a former value be overwritten? default = .true. logical , optional , intent ( in ) :: overwrite ! Local variables logical :: can_overwrite integer ( c_int ) :: cover , cerr character ( kind = c_char , len = 1 ), allocatable :: c_value (:), c_name (:) interface integer ( c_int ) function c_setenv ( envname , envval , overwrite ) & bind ( C , name = \"c_setenv\" ) import c_int , c_char implicit none !> Pointer to the name string character ( kind = c_char , len = 1 ), intent ( in ) :: envname ( * ) !> Pointer to the value string character ( kind = c_char , len = 1 ), intent ( in ) :: envval ( * ) !> Overwrite option integer ( c_int ), intent ( in ), value :: overwrite end function c_setenv end interface !> Overwrite setting can_overwrite = . true . if ( present ( overwrite )) can_overwrite = overwrite cover = merge ( 1_c_int , 0_c_int , can_overwrite ) !> C strings call f2cs ( name , c_name ) call f2cs ( value , c_value ) !> Call setenv #ifndef FPM_BOOTSTRAP cerr = c_setenv ( c_name , c_value , cover ) #endif set_env = cerr == 0_c_int end function set_env !> Deletes an environment variable for the current environment using the C standard library !> Returns an error if the variable did not exist in the first place logical function delete_env ( name ) result ( success ) !> Variable name character ( * ), intent ( in ) :: name ! Local variables integer ( c_int ) :: cerr character ( kind = c_char , len = 1 ), allocatable :: c_name (:) interface integer ( c_int ) function c_unsetenv ( envname ) bind ( C , name = \"c_unsetenv\" ) import c_int , c_char implicit none !> Pointer to the name string character ( kind = c_char , len = 1 ), intent ( in ) :: envname ( * ) end function c_unsetenv end interface !> C strings call f2cs ( name , c_name ) !> Call setenv #ifndef FPM_BOOTSTRAP cerr = c_unsetenv ( c_name ) #endif success = cerr == 0_c_int end function delete_env !> Fortran to C allocatable string pure subroutine f2cs ( f , c ) use iso_c_binding , only : c_char , c_null_char character ( * ), intent ( in ) :: f character ( len = 1 , kind = c_char ), allocatable , intent ( out ) :: c (:) integer :: lf , i lf = len ( f ) allocate ( c ( lf + 1 )) c ( lf + 1 ) = c_null_char forall ( i = 1 : lf ) c ( i ) = f ( i : i ) end subroutine f2cs end module fpm_environment","tags":"","loc":"sourcefile/fpm_environment.f90.html"},{"title":"fpm_backend_console.f90 – Fortran-lang/fpm","text":"Source Code !># Build Backend Console !> This module provides a lightweight implementation for printing to the console !> and updating previously-printed console lines. It used by `[[fpm_backend_output]]` !> for pretty-printing build status and progress. !> !> @note The implementation for updating previous lines relies on no other output !> going to `stdout`/`stderr` except through the `console_t` object provided. !> !> @note All write statements to `stdout` are enclosed within OpenMP `critical` regions !> module fpm_backend_console use iso_fortran_env , only : stdout => output_unit implicit none private public :: console_t public :: LINE_RESET public :: COLOR_RED , COLOR_GREEN , COLOR_YELLOW , COLOR_RESET character ( len =* ), parameter :: ESC = char ( 27 ) !> Escape code for erasing current line character ( len =* ), parameter :: LINE_RESET = ESC // \"[2K\" // ESC // \"[1G\" !> Escape code for moving up one line character ( len =* ), parameter :: LINE_UP = ESC // \"[1A\" !> Escape code for moving down one line character ( len =* ), parameter :: LINE_DOWN = ESC // \"[1B\" !> Escape code for red foreground color character ( len =* ), parameter :: COLOR_RED = ESC // \"[31m\" !> Escape code for green foreground color character ( len =* ), parameter :: COLOR_GREEN = ESC // \"[32m\" !> Escape code for yellow foreground color character ( len =* ), parameter :: COLOR_YELLOW = ESC // \"[93m\" !> Escape code to reset foreground color character ( len =* ), parameter :: COLOR_RESET = ESC // \"[0m\" !> Console object type console_t !> Number of lines printed integer :: n_line = 1 contains !> Write a single line to the console procedure :: write_line => console_write_line !> Update a previously-written console line procedure :: update_line => console_update_line end type console_t contains !> Write a single line to the standard output subroutine console_write_line ( console , str , line , advance ) !> Console object class ( console_t ), intent ( inout ) :: console !> String to write character ( * ), intent ( in ) :: str !> Integer needed to later update console line integer , intent ( out ), optional :: line !> Advancing output (print newline?) logical , intent ( in ), optional :: advance character ( 3 ) :: adv adv = \"yes\" if ( present ( advance )) then if (. not . advance ) then adv = \"no\" end if end if !$omp critical if ( present ( line )) then line = console % n_line end if write ( stdout , '(A)' , advance = trim ( adv )) LINE_RESET // str if ( adv == \"yes\" ) then console % n_line = console % n_line + 1 end if !$omp end critical end subroutine console_write_line !> Overwrite a previously-written line in standard output subroutine console_update_line ( console , line_no , str ) !> Console object class ( console_t ), intent ( in ) :: console !> Integer output from `[[console_write_line]]` integer , intent ( in ) :: line_no !> New string to overwrite line character ( * ), intent ( in ) :: str integer :: n !$omp critical n = console % n_line - line_no ! Step back to line write ( stdout , '(A)' , advance = \"no\" ) repeat ( LINE_UP , n ) // LINE_RESET write ( stdout , '(A)' , advance = \"no\" ) str ! Step forward to end write ( stdout , '(A)' , advance = \"no\" ) repeat ( LINE_DOWN , n ) // LINE_RESET !$omp end critical end subroutine console_update_line end module fpm_backend_console","tags":"","loc":"sourcefile/fpm_backend_console.f90.html"},{"title":"fortran.f90 – Fortran-lang/fpm","text":"Source Code module fpm_manifest_fortran use fpm_error , only : error_t , syntax_error , fatal_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , serializable_t , set_value , set_string implicit none private public :: fortran_config_t , new_fortran_config !> Configuration data for Fortran type , extends ( serializable_t ) :: fortran_config_t !> Enable default implicit typing logical :: implicit_typing = . false . !> Enable implicit external interfaces logical :: implicit_external = . false . !> Form to use for all Fortran sources character (:), allocatable :: source_form contains !> Serialization interface procedure :: serializable_is_same => fortran_is_same procedure :: dump_to_toml procedure :: load_from_toml end type fortran_config_t character ( len =* ), parameter , private :: class_name = 'fortran_config_t' contains !> Construct a new build configuration from a TOML data structure subroutine new_fortran_config ( self , table , error ) !> Instance of the fortran configuration type ( fortran_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat character (:), allocatable :: source_form call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"implicit-typing\" , self % implicit_typing , . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'implicit-typing' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"implicit-external\" , self % implicit_external , . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'implicit-external' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"source-form\" , source_form , \"free\" , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'source-form' in fpm.toml, expecting logical\" ) return end if select case ( source_form ) case default call fatal_error ( error , \"Value of source-form cannot be '\" // source_form // \"'\" ) return case ( \"free\" , \"fixed\" , \"default\" ) self % source_form = source_form end select end subroutine new_fortran_config !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_keys ( list ) ! table can be empty if ( size ( list ) < 1 ) return do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case ( \"implicit-typing\" , \"implicit-external\" , \"source-form\" ) continue case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in fortran\" ) exit end select end do end subroutine check logical function fortran_is_same ( this , that ) class ( fortran_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that fortran_is_same = . false . select type ( other => that ) type is ( fortran_config_t ) if ( this % implicit_typing . neqv . other % implicit_typing ) return if ( this % implicit_external . neqv . other % implicit_external ) return if (. not . allocated ( this % source_form ). eqv . allocated ( other % source_form )) return if (. not . this % source_form == other % source_form ) return class default ! Not the same type return end select !> All checks passed! fortran_is_same = . true . end function fortran_is_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( fortran_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_value ( table , \"implicit-typing\" , self % implicit_typing , error , class_name ) if ( allocated ( error )) return call set_value ( table , \"implicit-external\" , self % implicit_external , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"source-form\" , self % source_form , error , class_name ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( fortran_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"implicit-typing\" , self % implicit_typing , error , class_name ) if ( allocated ( error )) return call get_value ( table , \"implicit-external\" , self % implicit_external , error , class_name ) if ( allocated ( error )) return call get_value ( table , \"source-form\" , self % source_form ) end subroutine load_from_toml end module fpm_manifest_fortran","tags":"","loc":"sourcefile/fortran.f90.html"},{"title":"toml.f90 – Fortran-lang/fpm","text":"Source Code !># Interface to TOML processing library !> !> This module acts as a proxy to the `toml-f` public Fortran API and allows !> to selectively expose components from the library to `fpm`. !> The interaction with `toml-f` data types outside of this module should be !> limited to tables, arrays and key-lists, most of the necessary interactions !> are implemented in the building interface with the `get_value` and `set_value` !> procedures. !> !> This module allows to implement features necessary for `fpm`, which are !> not yet available in upstream `toml-f`. !> !> For more details on the library used see the !> [TOML-Fortran](https://toml-f.github.io/toml-f) developer pages. module fpm_toml use fpm_error , only : error_t , fatal_error , file_not_found_error use fpm_strings , only : string_t , str_ends_with , lower use tomlf , only : toml_table , toml_array , toml_key , toml_stat , get_value , & & set_value , toml_parse , toml_error , new_table , add_table , add_array , & & toml_serialize , len , toml_load , toml_value use tomlf_de_parser , only : parse use jonquil , only : json_serialize , json_error , json_value , json_object , json_load , & cast_to_object use iso_fortran_env , only : int64 implicit none private public :: read_package_file , toml_table , toml_array , toml_key , toml_stat , & get_value , set_value , get_list , new_table , add_table , add_array , len , & toml_error , toml_serialize , toml_load , check_keys , set_list , set_string , & name_is_json !> An abstract interface for any fpm class that should be fully serializable to/from TOML/JSON type , abstract , public :: serializable_t contains !> Dump to TOML table, unit, file procedure ( to_toml ), deferred :: dump_to_toml procedure , non_overridable , private :: dump_to_file procedure , non_overridable , private :: dump_to_unit generic :: dump => dump_to_toml , dump_to_file , dump_to_unit !> Load from TOML table, unit, file procedure ( from_toml ), deferred :: load_from_toml procedure , non_overridable , private :: load_from_file procedure , non_overridable , private :: load_from_unit generic :: load => load_from_toml , load_from_file , load_from_unit !> Serializable entities need a way to check that they're equal procedure ( is_equal ), deferred :: serializable_is_same generic :: operator ( == ) => serializable_is_same !> Test load/write roundtrip procedure , non_overridable :: test_serialization end type serializable_t !> add_table: fpm interface interface add_table module procedure add_table_fpm end interface add_table !> set_value: fpm interface interface set_value module procedure set_logical module procedure set_integer module procedure set_integer_64 end interface set_value interface set_string module procedure set_character module procedure set_string_type end interface set_string !> get_value: fpm interface interface get_value module procedure get_logical module procedure get_integer module procedure get_integer_64 end interface get_value abstract interface !> Write object to TOML datastructure subroutine to_toml ( self , table , error ) import serializable_t , toml_table , error_t implicit none !> Instance of the serializable object class ( serializable_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error end subroutine to_toml !> Read dependency tree from TOML data structure subroutine from_toml ( self , table , error ) import serializable_t , toml_table , error_t implicit none !> Instance of the serializable object class ( serializable_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error end subroutine from_toml !> Compare two serializable objects logical function is_equal ( this , that ) import serializable_t class ( serializable_t ), intent ( in ) :: this , that end function is_equal end interface contains !> Test serialization of a serializable object subroutine test_serialization ( self , message , error ) class ( serializable_t ), intent ( inout ) :: self character ( len =* ), intent ( in ) :: message type ( error_t ), allocatable , intent ( out ) :: error integer :: iunit , ii class ( serializable_t ), allocatable :: copy character ( len = 4 ), parameter :: formats ( 2 ) = [ 'TOML' , 'JSON' ] all_formats : do ii = 1 , 2 open ( newunit = iunit , form = 'formatted' , action = 'readwrite' , status = 'scratch' ) !> Dump to scratch file call self % dump ( iunit , error , json = ii == 2 ) if ( allocated ( error )) then error % message = formats ( ii ) // ': ' // error % message return endif !> Load from scratch file rewind ( iunit ) allocate ( copy , mold = self ) call copy % load ( iunit , error , json = ii == 2 ) if ( allocated ( error )) then error % message = formats ( ii ) // ': ' // error % message return endif close ( iunit ) !> Check same if (. not .( self == copy )) then call fatal_error ( error , 'serializable object failed ' // formats ( ii ) // & ' write/reread test: ' // trim ( message )) return end if deallocate ( copy ) end do all_formats end subroutine test_serialization !> Write serializable object to a formatted Fortran unit subroutine dump_to_unit ( self , unit , error , json ) !> Instance of the dependency tree class ( serializable_t ), intent ( inout ) :: self !> Formatted unit integer , intent ( in ) :: unit !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional JSON format requested? logical , optional , intent ( in ) :: json type ( toml_table ) :: table logical :: is_json is_json = . false .; if ( present ( json )) is_json = json table = toml_table () call self % dump ( table , error ) if ( is_json ) then ! !> Deactivate JSON serialization for now ! call fatal_error(error, 'JSON serialization option is not yet available') ! return write ( unit , '(a)' ) json_serialize ( table ) else write ( unit , '(a)' ) toml_serialize ( table ) end if call table % destroy () end subroutine dump_to_unit !> Write serializable object to file subroutine dump_to_file ( self , file , error , json ) !> Instance of the dependency tree class ( serializable_t ), intent ( inout ) :: self !> File name character ( len =* ), intent ( in ) :: file !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional JSON format logical , optional , intent ( in ) :: json integer :: unit open ( file = file , newunit = unit ) call self % dump ( unit , error , json ) close ( unit ) if ( allocated ( error )) return end subroutine dump_to_file !> Read dependency tree from file subroutine load_from_file ( self , file , error , json ) !> Instance of the dependency tree class ( serializable_t ), intent ( inout ) :: self !> File name character ( len =* ), intent ( in ) :: file !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional JSON format logical , optional , intent ( in ) :: json integer :: unit logical :: exist inquire ( file = file , exist = exist ) if (. not . exist ) return open ( file = file , newunit = unit ) call self % load ( unit , error , json ) close ( unit ) end subroutine load_from_file !> Read dependency tree from file subroutine load_from_unit ( self , unit , error , json ) !> Instance of the dependency tree class ( serializable_t ), intent ( inout ) :: self !> File name integer , intent ( in ) :: unit !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional JSON format logical , optional , intent ( in ) :: json type ( toml_error ), allocatable :: local_error type ( toml_table ), allocatable :: table type ( toml_table ), pointer :: jtable class ( toml_value ), allocatable :: object logical :: is_json is_json = . false .; if ( present ( json )) is_json = json if ( is_json ) then !> init JSON interpreter call json_load ( object , unit , error = local_error ) if ( allocated ( local_error )) then allocate ( error ) call move_alloc ( local_error % message , error % message ) return end if jtable => cast_to_object ( object ) if (. not . associated ( jtable )) then call fatal_error ( error , 'cannot initialize JSON table ' ) return end if !> Read object from TOML table call self % load ( jtable , error ) else !> use default TOML parser call toml_load ( table , unit , error = local_error ) if ( allocated ( local_error )) then allocate ( error ) call move_alloc ( local_error % message , error % message ) return end if !> Read object from TOML table call self % load ( table , error ) endif if ( allocated ( error )) return end subroutine load_from_unit !> Process the configuration file to a TOML data structure subroutine read_package_file ( table , manifest , error ) !> TOML data structure type ( toml_table ), allocatable , intent ( out ) :: table !> Name of the package configuration file character ( len =* ), intent ( in ) :: manifest !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error type ( toml_error ), allocatable :: parse_error integer :: unit logical :: exist inquire ( file = manifest , exist = exist ) if (. not . exist ) then call file_not_found_error ( error , manifest ) return end if open ( file = manifest , newunit = unit ) call toml_load ( table , unit , error = parse_error ) close ( unit ) if ( allocated ( parse_error )) then allocate ( error ) call move_alloc ( parse_error % message , error % message ) return end if end subroutine read_package_file subroutine get_list ( table , key , list , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Key to read from character ( len =* ), intent ( in ) :: key !> List of strings to read type ( string_t ), allocatable , intent ( out ) :: list (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , ilist , nlist type ( toml_array ), pointer :: children character ( len = :), allocatable :: str if (. not . table % has_key ( key )) return call get_value ( table , key , children , requested = . false .) if ( associated ( children )) then nlist = len ( children ) allocate ( list ( nlist )) do ilist = 1 , nlist call get_value ( children , ilist , str , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Entry in \" // key // \" field cannot be read\" ) exit end if call move_alloc ( str , list ( ilist )% s ) end do if ( allocated ( error )) return else call get_value ( table , key , str , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Entry in \" // key // \" field cannot be read\" ) return end if if ( allocated ( str )) then allocate ( list ( 1 )) call move_alloc ( str , list ( 1 )% s ) end if end if end subroutine get_list ! Set string array subroutine set_list ( table , key , list , error ) !> Instance of the string array type ( string_t ), allocatable , intent ( in ) :: list (:) !> Key to save to character ( len =* ), intent ( in ) :: key !> Instance of the toml table type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: stat , ilist type ( toml_array ), pointer :: children character ( len = :), allocatable :: str !> Set no key if array is not present if (. not . allocated ( list )) return !> Check the key is not empty if ( len_trim ( key ) <= 0 ) then call fatal_error ( error , 'key is empty dumping string array to TOML table' ) return end if if ( size ( list ) /= 1 ) then ! includes empty list case !> String array call add_array ( table , key , children , stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Cannot set array table in \" // key // \" field\" ) return end if do ilist = 1 , size ( list ) call set_value ( children , ilist , list ( ilist )% s , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Cannot store array entry in \" // key // \" field\" ) return end if end do else ! Single value: set string call set_value ( table , key , list ( 1 )% s , stat = stat ) if ( stat /= toml_stat % success ) & call fatal_error ( error , \"Cannot store entry in \" // key // \" field\" ) return end if end subroutine set_list !> Function wrapper to set a character(len=:), allocatable variable to a toml table subroutine set_character ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys to check. character ( len =* ), intent ( in ) :: key !> The character variable character ( len =* ), optional , intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr !> Check the key is not empty if ( len_trim ( key ) <= 0 ) then call fatal_error ( error , 'key is empty setting character string to TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if if ( present ( var )) then call set_value ( table , key , var , ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot set character key <' // key // '> in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if endif end subroutine set_character !> Function wrapper to set a logical variable to a toml table, returning an fpm error subroutine set_logical ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable logical , intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call set_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot set logical key <' // key // '> in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine set_logical !> Function wrapper to set a default integer variable to a toml table, returning an fpm error subroutine set_integer ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable integer , intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call set_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot set integer key <' // key // '> in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine set_integer !> Function wrapper to set a default integer variable to a toml table, returning an fpm error subroutine set_integer_64 ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable integer ( int64 ), intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call set_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot set integer(int64) key <' // key // '> in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine set_integer_64 !> Function wrapper to set a character(len=:), allocatable variable to a toml table subroutine set_string_type ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys to check. character ( len =* ), intent ( in ) :: key !> The character variable type ( string_t ), intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt call set_character ( table , key , var % s , error , whereAt ) end subroutine set_string_type !> Function wrapper to add a toml table and return an fpm error subroutine add_table_fpm ( table , key , ptr , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Table key character ( len =* ), intent ( in ) :: key !> The character variable type ( toml_table ), pointer , intent ( out ) :: ptr !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr !> Nullify pointer nullify ( ptr ) call add_table ( table , key , ptr , ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot add <' // key // '> table in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine add_table_fpm !> Function wrapper to get a logical variable from a toml table, returning an fpm error subroutine get_logical ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable logical , intent ( inout ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call get_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot get logical key <' // key // '> from TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine get_logical !> Function wrapper to get a default integer variable from a toml table, returning an fpm error subroutine get_integer ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable integer , intent ( inout ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call get_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot get integer key <' // key // '> from TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine get_integer !> Function wrapper to get a integer(int64) variable from a toml table, returning an fpm error subroutine get_integer_64 ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable integer ( int64 ), intent ( inout ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call get_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot get integer(int64) key <' // key // '> from TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine get_integer_64 !> Check if table contains only keys that are part of the list. If a key is !> found that is not part of the list, an error is allocated. subroutine check_keys ( table , valid_keys , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys to check. character ( len =* ), intent ( in ) :: valid_keys (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: keys (:) type ( toml_table ), pointer :: child character (:), allocatable :: name , value , valid_keys_string integer :: ikey , ivalid call table % get_key ( name ) call table % get_keys ( keys ) do ikey = 1 , size ( keys ) if (. not . any ( keys ( ikey )% key == valid_keys )) then ! Generate error message valid_keys_string = new_line ( 'a' ) // new_line ( 'a' ) do ivalid = 1 , size ( valid_keys ) valid_keys_string = valid_keys_string // trim ( valid_keys ( ivalid )) // new_line ( 'a' ) end do allocate ( error ) error % message = \"Key '\" // keys ( ikey )% key // \"' not allowed in the '\" // & & name // \"' table.\" // new_line ( 'a' ) // new_line ( 'a' ) // 'Valid keys: ' // valid_keys_string return end if ! Check if value can be mapped or else (wrong type) show error message with the error location. ! Right now, it can only be mapped to a string or to a child node, but this can be extended in the future. call get_value ( table , keys ( ikey )% key , value ) if (. not . allocated ( value )) then ! If value is not a string, check if it is a child node call get_value ( table , keys ( ikey )% key , child ) if (. not . associated ( child )) then allocate ( error ) error % message = \"'\" // name // \"' has an invalid '\" // keys ( ikey )% key // \"' entry.\" return endif end if end do end subroutine check_keys !> Choose between JSON or TOML based on a file name logical function name_is_json ( filename ) character ( * ), intent ( in ) :: filename character ( * ), parameter :: json_identifier = \".json\" name_is_json = . false . if ( len_trim ( filename ) < len ( json_identifier )) return name_is_json = str_ends_with ( lower ( filename ), json_identifier ) end function name_is_json end module fpm_toml","tags":"","loc":"sourcefile/toml.f90.html"},{"title":"install.f90 – Fortran-lang/fpm","text":"Source Code module fpm_cmd_install use , intrinsic :: iso_fortran_env , only : output_unit use fpm , only : build_model use fpm_backend , only : build_package use fpm_command_line , only : fpm_install_settings use fpm_error , only : error_t , fatal_error , fpm_stop use fpm_filesystem , only : join_path , list_files use fpm_installer , only : installer_t , new_installer use fpm_manifest , only : package_config_t , get_package_data use fpm_model , only : fpm_model_t , FPM_SCOPE_APP use fpm_targets , only : targets_from_sources , build_target_t , & build_target_ptr , FPM_TARGET_EXECUTABLE , & filter_library_targets , filter_executable_targets , filter_modules use fpm_strings , only : string_t , resize implicit none private public :: cmd_install contains !> Entry point for the fpm-install subcommand subroutine cmd_install ( settings ) !> Representation of the command line settings type ( fpm_install_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( error_t ), allocatable :: error type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( installer_t ) :: installer type ( string_t ), allocatable :: list (:) logical :: installable integer :: ntargets call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) call build_model ( model , settings , package , error ) call handle_error ( error ) call targets_from_sources ( targets , model , settings % prune , error ) call handle_error ( error ) call install_info ( output_unit , settings % list , targets , ntargets ) if ( settings % list ) return installable = ( allocated ( package % library ) . and . package % install % library ) & . or . allocated ( package % executable ) . or . ntargets > 0 if (. not . installable ) then call fatal_error ( error , \"Project does not contain any installable targets\" ) call handle_error ( error ) end if if (. not . settings % no_rebuild ) then call build_package ( targets , model , verbose = settings % verbose ) end if call new_installer ( installer , prefix = settings % prefix , & bindir = settings % bindir , libdir = settings % libdir , & includedir = settings % includedir , & verbosity = merge ( 2 , 1 , settings % verbose )) if ( allocated ( package % library ) . and . package % install % library ) then call filter_library_targets ( targets , list ) if ( size ( list ) > 0 ) then call installer % install_library ( list ( 1 )% s , error ) call handle_error ( error ) call install_module_files ( installer , targets , error ) call handle_error ( error ) end if end if if ( allocated ( package % executable ) . or . ntargets > 0 ) then call install_executables ( installer , targets , error ) call handle_error ( error ) end if end subroutine cmd_install subroutine install_info ( unit , verbose , targets , ntargets ) integer , intent ( in ) :: unit logical , intent ( in ) :: verbose type ( build_target_ptr ), intent ( in ) :: targets (:) integer , intent ( out ) :: ntargets integer :: ii type ( string_t ), allocatable :: install_target (:), temp (:) allocate ( install_target ( 0 )) call filter_library_targets ( targets , temp ) install_target = [ install_target , temp ] call filter_executable_targets ( targets , FPM_SCOPE_APP , temp ) install_target = [ install_target , temp ] ntargets = size ( install_target ) if ( verbose ) then write ( unit , '(\"#\", *(1x, g0))' ) & \"total number of installable targets:\" , ntargets do ii = 1 , ntargets write ( unit , '(\"-\", *(1x, g0))' ) install_target ( ii )% s end do endif end subroutine install_info subroutine install_module_files ( installer , targets , error ) type ( installer_t ), intent ( inout ) :: installer type ( build_target_ptr ), intent ( in ) :: targets (:) type ( error_t ), allocatable , intent ( out ) :: error type ( string_t ), allocatable :: modules (:) integer :: ii call filter_modules ( targets , modules ) do ii = 1 , size ( modules ) call installer % install_header ( modules ( ii )% s // \".mod\" , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return end subroutine install_module_files subroutine install_executables ( installer , targets , error ) type ( installer_t ), intent ( inout ) :: installer type ( build_target_ptr ), intent ( in ) :: targets (:) type ( error_t ), allocatable , intent ( out ) :: error integer :: ii do ii = 1 , size ( targets ) if ( targets ( ii )% ptr % is_executable_target ( FPM_SCOPE_APP )) then call installer % install_executable ( targets ( ii )% ptr % output_file , error ) if ( allocated ( error )) exit end if end do if ( allocated ( error )) return end subroutine install_executables subroutine handle_error ( error ) type ( error_t ), intent ( in ), optional :: error if ( present ( error )) then call fpm_stop ( 1 , '*cmd_install* error: ' // error % message ) end if end subroutine handle_error end module fpm_cmd_install","tags":"","loc":"sourcefile/install.f90~2.html"},{"title":"installer.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of an installer object. !> !> The installer provides a way to install objects to their respective directories !> in the installation prefix, a generic install command allows to install !> to any directory within the prefix. module fpm_installer use , intrinsic :: iso_fortran_env , only : output_unit use fpm_environment , only : get_os_type , os_is_unix use fpm_error , only : error_t , fatal_error use fpm_filesystem , only : join_path , mkdir , exists , unix_path , windows_path , get_local_prefix implicit none private public :: installer_t , new_installer !> Declaration of the installer type type :: installer_t !> Path to installation directory character ( len = :), allocatable :: prefix !> Binary dir relative to the installation prefix character ( len = :), allocatable :: bindir !> Library directory relative to the installation prefix character ( len = :), allocatable :: libdir !> Include directory relative to the installation prefix character ( len = :), allocatable :: includedir !> Output unit for informative printout integer :: unit = output_unit !> Verbosity of the installer integer :: verbosity = 1 !> Command to copy objects into the installation prefix character ( len = :), allocatable :: copy !> Command to move objects into the installation prefix character ( len = :), allocatable :: move !> Cached operating system integer :: os contains !> Install an executable in its correct subdirectory procedure :: install_executable !> Install a library in its correct subdirectory procedure :: install_library !> Install a header/module in its correct subdirectory procedure :: install_header !> Install a generic file into a subdirectory in the installation prefix procedure :: install !> Run an installation command, type-bound for unit testing purposes procedure :: run !> Create a new directory in the prefix, type-bound for unit testing purposes procedure :: make_dir end type installer_t !> Default name of the binary subdirectory character ( len =* ), parameter :: default_bindir = \"bin\" !> Default name of the library subdirectory character ( len =* ), parameter :: default_libdir = \"lib\" !> Default name of the include subdirectory character ( len =* ), parameter :: default_includedir = \"include\" !> Copy command on Unix platforms character ( len =* ), parameter :: default_copy_unix = \"cp\" !> Copy command on Windows platforms character ( len =* ), parameter :: default_copy_win = \"copy\" !> Copy command on Unix platforms character ( len =* ), parameter :: default_force_copy_unix = \"cp -f\" !> Copy command on Windows platforms character ( len =* ), parameter :: default_force_copy_win = \"copy /Y\" !> Move command on Unix platforms character ( len =* ), parameter :: default_move_unix = \"mv\" !> Move command on Windows platforms character ( len =* ), parameter :: default_move_win = \"move\" contains !> Create a new instance of an installer subroutine new_installer ( self , prefix , bindir , libdir , includedir , verbosity , & copy , move ) !> Instance of the installer type ( installer_t ), intent ( out ) :: self !> Path to installation directory character ( len =* ), intent ( in ), optional :: prefix !> Binary dir relative to the installation prefix character ( len =* ), intent ( in ), optional :: bindir !> Library directory relative to the installation prefix character ( len =* ), intent ( in ), optional :: libdir !> Include directory relative to the installation prefix character ( len =* ), intent ( in ), optional :: includedir !> Verbosity of the installer integer , intent ( in ), optional :: verbosity !> Copy command character ( len =* ), intent ( in ), optional :: copy !> Move command character ( len =* ), intent ( in ), optional :: move self % os = get_os_type () ! By default, never prompt the user for overwrites if ( present ( copy )) then self % copy = copy else if ( os_is_unix ( self % os )) then self % copy = default_force_copy_unix else self % copy = default_force_copy_win end if end if if ( present ( move )) then self % move = move else if ( os_is_unix ( self % os )) then self % move = default_move_unix else self % move = default_move_win end if end if if ( present ( includedir )) then self % includedir = includedir else self % includedir = default_includedir end if if ( present ( prefix )) then self % prefix = prefix else self % prefix = get_local_prefix ( self % os ) end if if ( present ( bindir )) then self % bindir = bindir else self % bindir = default_bindir end if if ( present ( libdir )) then self % libdir = libdir else self % libdir = default_libdir end if if ( present ( verbosity )) then self % verbosity = verbosity else self % verbosity = 1 end if end subroutine new_installer !> Install an executable in its correct subdirectory subroutine install_executable ( self , executable , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Path to the executable character ( len =* ), intent ( in ) :: executable !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ll if (. not . os_is_unix ( self % os )) then ll = len ( executable ) if ( executable ( max ( 1 , ll - 3 ): ll ) /= \".exe\" ) then call self % install ( executable // \".exe\" , self % bindir , error ) return end if end if call self % install ( executable , self % bindir , error ) end subroutine install_executable !> Install a library in its correct subdirectory subroutine install_library ( self , library , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Path to the library character ( len =* ), intent ( in ) :: library !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call self % install ( library , self % libdir , error ) end subroutine install_library !> Install a header/module in its correct subdirectory subroutine install_header ( self , header , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Path to the header character ( len =* ), intent ( in ) :: header !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call self % install ( header , self % includedir , error ) end subroutine install_header !> Install a generic file into a subdirectory in the installation prefix subroutine install ( self , source , destination , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Path to the original file character ( len =* ), intent ( in ) :: source !> Path to the destination inside the prefix character ( len =* ), intent ( in ) :: destination !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: install_dest install_dest = join_path ( self % prefix , destination ) if ( os_is_unix ( self % os )) then install_dest = unix_path ( install_dest ) else install_dest = windows_path ( install_dest ) end if call self % make_dir ( install_dest , error ) if ( allocated ( error )) return if ( self % verbosity > 0 ) then if ( exists ( install_dest )) then write ( self % unit , '(\"# Update:\", 1x, a, 1x, \"->\", 1x, a)' ) & source , install_dest else write ( self % unit , '(\"# Install:\", 1x, a, 1x, \"->\", 1x, a)' ) & source , install_dest end if end if ! Use force-copy to never prompt the user for overwrite if a package was already installed call self % run ( self % copy // ' \"' // source // '\" \"' // install_dest // '\"' , error ) if ( allocated ( error )) return end subroutine install !> Create a new directory in the prefix subroutine make_dir ( self , dir , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Directory to be created character ( len =* ), intent ( in ) :: dir !> Error handling type ( error_t ), allocatable , intent ( out ) :: error if (. not . exists ( dir )) then if ( self % verbosity > 1 ) then write ( self % unit , '(\"# Dir:\", 1x, a)' ) dir end if call mkdir ( dir ) end if end subroutine make_dir !> Run an installation command subroutine run ( self , command , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Command to be launched character ( len =* ), intent ( in ) :: command !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat if ( self % verbosity > 1 ) then write ( self % unit , '(\"# Run:\", 1x, a)' ) command end if call execute_command_line ( command , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed in command: '\" // command // \"'\" ) return end if end subroutine run end module fpm_installer","tags":"","loc":"sourcefile/installer.f90.html"},{"title":"fpm_strings.f90 – Fortran-lang/fpm","text":"Source Code !> This module defines general procedures for **string operations** for both CHARACTER and !! TYPE(STRING_T) variables ! !>## general routines for performing __string operations__ !! !!### Types !! - **TYPE(STRING_T)** define a type to contain strings of variable length !!### Type Conversions !! - [[F_STRING]] return Fortran **CHARACTER** variable when given a C-like array of !! single characters terminated with a C_NULL_CHAR **CHARACTER** !! - [[STR]] Converts **INTEGER** or** LOGICAL** to **CHARACTER** string !!### Case !! - [[LOWER]] Changes a string to lowercase over optional specified column range !!### Parsing and joining !! - [[SPLIT]] parse string on delimiter characters and store tokens into an allocatable array !! - [[SPLIT_FIRST_LAST]] Computes the first and last indices of tokens in input string, delimited by the characters in set, !! and stores them into first and last output arrays. !! - [[STRING_CAT]] Concatenate an array of **type(string_t)** into a single **CHARACTER** variable !! - [[JOIN]] append an array of **CHARACTER** variables into a single **CHARACTER** variable !!### Testing !! - [[STR_ENDS_WITH]] test if a **CHARACTER** string or array ends with a specified suffix !! - [[STRING_ARRAY_CONTAINS]] Check if array of **TYPE(STRING_T)** matches a particular **CHARACTER** string !! - **OPERATOR(.IN.)** Check if array of **TYPE(STRING_T)** matches a particular **CHARACTER** string !! - [[GLOB]] function compares text strings, one of which can have wildcards ('*' or '?'). !! - [[IS_FORTRAN_NAME]] determine whether a string is an acceptable Fortran entity name !! - [[TO_FORTRAN_NAME]] replace allowed special but unusuable characters in names with underscore !!### Whitespace !! - [[NOTABS]] subroutine to expand tab characters assuming a tab space every eight characters !! - [[DILATE]] function to expand tab characters assuming a tab space every eight characters !! - [[LEN_TRIM]] Determine total trimmed length of **STRING_T** array !!### Miscellaneous !! - [[FNV_1A]] Hash a **CHARACTER(*)** string of default kind or a **TYPE(STRING_T)** array !! - [[REPLACE]] Returns string with characters in charset replaced with target_char. !! - [[RESIZE]] increase the size of a **TYPE(STRING_T)** array by N elements !! module fpm_strings use iso_fortran_env , only : int64 use , intrinsic :: iso_fortran_env , only : stdin => input_unit , & & stdout => output_unit , & & stderr => error_unit use iso_c_binding , only : c_char , c_ptr , c_int , c_null_char , c_associated , c_f_pointer , c_size_t implicit none private public :: f_string , lower , upper , split , split_first_last , str_ends_with , string_t , str_begins_with_str public :: to_fortran_name , is_fortran_name public :: string_array_contains , string_cat , len_trim , operator (. in .), fnv_1a public :: replace , resize , str , join , glob public :: notabs , dilate , remove_newline_characters , remove_characters_in_set public :: operator ( == ) !> Module naming public :: is_valid_module_name , is_valid_module_prefix , & has_valid_custom_prefix , has_valid_standard_prefix , & module_prefix_template , module_prefix_type type string_t character ( len = :), allocatable :: s end type interface len_trim module procedure :: string_len_trim module procedure :: strings_len_trim end interface len_trim interface resize module procedure :: resize_string end interface interface operator (. in .) module procedure string_array_contains end interface interface fnv_1a procedure :: fnv_1a_char procedure :: fnv_1a_string_t end interface fnv_1a interface str_ends_with procedure :: str_ends_with_str procedure :: str_ends_with_any procedure :: str_ends_with_any_string end interface str_ends_with interface str module procedure str_int , str_int64 , str_logical end interface interface string_t module procedure new_string_t end interface string_t interface f_string module procedure f_string , f_string_cptr , f_string_cptr_n end interface f_string interface operator ( == ) module procedure string_is_same module procedure string_arrays_same end interface contains !> test if a CHARACTER string ends with a specified suffix pure logical function str_ends_with_str ( s , e ) result ( r ) character ( * ), intent ( in ) :: s , e integer :: n1 , n2 n1 = len ( s ) - len ( e ) + 1 n2 = len ( s ) if ( n1 < 1 ) then r = . false . else r = ( s ( n1 : n2 ) == e ) end if end function str_ends_with_str !> test if a CHARACTER string ends with any of an array of suffixs pure logical function str_ends_with_any ( s , e ) result ( r ) character ( * ), intent ( in ) :: s character ( * ), intent ( in ) :: e (:) integer :: i r = . true . do i = 1 , size ( e ) if ( str_ends_with ( s , trim ( e ( i )))) return end do r = . false . end function str_ends_with_any !> Test if a CHARACTER string ends with any of an array of string suffixs pure logical function str_ends_with_any_string ( s , e ) result ( r ) character ( * ), intent ( in ) :: s type ( string_t ), intent ( in ) :: e (:) integer :: i r = . true . do i = 1 , size ( e ) if ( str_ends_with ( s , trim ( e ( i )% s ))) return end do r = . false . end function str_ends_with_any_string !> test if a CHARACTER string begins with a specified prefix pure logical function str_begins_with_str ( s , e , case_sensitive ) result ( r ) character ( * ), intent ( in ) :: s , e logical , optional , intent ( in ) :: case_sensitive ! Default option: case sensitive integer :: n1 , n2 logical :: lower_case ! Check if case sensitive if ( present ( case_sensitive )) then lower_case = . not . case_sensitive else lower_case = . false . end if n1 = 1 n2 = 1 + len ( e ) - 1 if ( n2 > len ( s )) then r = . false . elseif ( lower_case ) then r = lower ( s ( n1 : n2 )) == lower ( e ) else r = ( s ( n1 : n2 ) == e ) end if end function str_begins_with_str !> return Fortran character variable when given a C-like array of !! single characters terminated with a C_NULL_CHAR character function f_string ( c_string ) use iso_c_binding character ( len = 1 ), intent ( in ) :: c_string (:) character (:), allocatable :: f_string integer :: i , n i = 0 do while ( c_string ( i + 1 ) /= C_NULL_CHAR ) i = i + 1 end do n = i allocate ( character ( n ) :: f_string ) do i = 1 , n f_string ( i : i ) = c_string ( i ) end do end function f_string !> return Fortran character variable when given a null-terminated c_ptr function f_string_cptr ( cptr ) result ( s ) type ( c_ptr ), intent ( in ), value :: cptr character ( len = :, kind = c_char ), allocatable :: s interface function c_strlen ( s ) result ( r ) bind ( c , name = \"strlen\" ) import c_size_t , c_ptr type ( c_ptr ), intent ( in ), value :: s integer ( kind = c_size_t ) :: r end function end interface s = f_string_cptr_n ( cptr , c_strlen ( cptr )) end function !> return Fortran character variable when given a null-terminated c_ptr and its length function f_string_cptr_n ( cptr , n ) result ( s ) type ( c_ptr ), intent ( in ), value :: cptr integer ( kind = c_size_t ), intent ( in ) :: n character ( len = n , kind = c_char ) :: s character ( len = n , kind = c_char ), pointer :: sptr call c_f_pointer ( cptr , sptr ) s = sptr end function !> Hash a character(*) string of default kind pure function fnv_1a_char ( input , seed ) result ( hash ) character ( * ), intent ( in ) :: input integer ( int64 ), intent ( in ), optional :: seed integer ( int64 ) :: hash integer :: i integer ( int64 ), parameter :: FNV_OFFSET_32 = 2166136261_int64 integer ( int64 ), parameter :: FNV_PRIME_32 = 16777619_int64 if ( present ( seed )) then hash = seed else hash = FNV_OFFSET_32 end if do i = 1 , len ( input ) hash = ieor ( hash , iachar ( input ( i : i ), int64 )) * FNV_PRIME_32 end do end function fnv_1a_char !> Hash a string_t array of default kind pure function fnv_1a_string_t ( input , seed ) result ( hash ) type ( string_t ), intent ( in ) :: input (:) integer ( int64 ), intent ( in ), optional :: seed integer ( int64 ) :: hash integer :: i hash = fnv_1a ( input ( 1 )% s , seed ) do i = 2 , size ( input ) hash = fnv_1a ( input ( i )% s , hash ) end do end function fnv_1a_string_t !>Author: John S. Urban !!License: Public Domain !! Changes a string to lowercase over optional specified column range elemental pure function lower ( str , begin , end ) result ( string ) character ( * ), intent ( In ) :: str character ( len ( str )) :: string integer , intent ( in ), optional :: begin , end integer :: i integer :: ibegin , iend string = str ibegin = 1 if ( present ( begin )) then ibegin = max ( ibegin , begin ) endif iend = len_trim ( str ) if ( present ( end )) then iend = min ( iend , end ) endif do i = ibegin , iend ! step thru each letter in the string in specified range select case ( str ( i : i )) case ( 'A' : 'Z' ) string ( i : i ) = char ( iachar ( str ( i : i )) + 32 ) ! change letter to miniscule case default end select end do end function lower !!License: Public Domain !! Changes a string to upprtcase over optional specified column range elemental pure function upper ( str , begin , end ) result ( string ) character ( * ), intent ( In ) :: str character ( len ( str )) :: string integer , intent ( in ), optional :: begin , end integer :: i integer :: ibegin , iend string = str ibegin = 1 if ( present ( begin )) then ibegin = max ( ibegin , begin ) endif iend = len_trim ( str ) if ( present ( end )) then iend = min ( iend , end ) endif do i = ibegin , iend ! step thru each letter in the string in specified range select case ( str ( i : i )) case ( 'a' : 'z' ) string ( i : i ) = char ( iachar ( str ( i : i )) - 32 ) ! change letter to capitalized case default end select end do end function upper !> Helper function to generate a new string_t instance !> (Required due to the allocatable component) function new_string_t ( s ) result ( string ) character ( * ), intent ( in ) :: s type ( string_t ) :: string string % s = s end function new_string_t !> Check if array of TYPE(STRING_T) matches a particular CHARACTER string !! logical function string_array_contains ( search_string , array ) character ( * ), intent ( in ) :: search_string type ( string_t ), intent ( in ) :: array (:) integer :: i string_array_contains = any ([( array ( i )% s == search_string , & i = 1 , size ( array ))]) end function string_array_contains !> Concatenate an array of type(string_t) into !> a single CHARACTER variable function string_cat ( strings , delim ) result ( cat ) type ( string_t ), intent ( in ) :: strings (:) character ( * ), intent ( in ), optional :: delim character (:), allocatable :: cat integer :: i character (:), allocatable :: delim_str if ( size ( strings ) < 1 ) then cat = '' return end if if ( present ( delim )) then delim_str = delim else delim_str = '' end if cat = strings ( 1 )% s do i = 2 , size ( strings ) cat = cat // delim_str // strings ( i )% s end do end function string_cat !> Determine total trimmed length of `string_t` array pure function strings_len_trim ( strings ) result ( n ) type ( string_t ), intent ( in ) :: strings (:) integer :: i , n n = 0 do i = 1 , size ( strings ) n = n + len_trim ( strings ( i )% s ) end do end function strings_len_trim !> Determine total trimmed length of `string_t` array elemental integer function string_len_trim ( string ) result ( n ) type ( string_t ), intent ( in ) :: string if ( allocated ( string % s )) then n = len_trim ( string % s ) else n = 0 end if end function string_len_trim !>Author: John S. Urban !!License: Public Domain !! parse string on delimiter characters and store tokens into an allocatable array subroutine split ( input_line , array , delimiters , order , nulls ) !! given a line of structure \" par1 par2 par3 ... parn \" store each par(n) into a separate variable in array. !! !! * by default adjacent delimiters in the input string do not create an empty string in the output array !! * no quoting of delimiters is supported character ( len =* ), intent ( in ) :: input_line !! input string to tokenize character ( len =* ), optional , intent ( in ) :: delimiters !! list of delimiter characters character ( len =* ), optional , intent ( in ) :: order !! order of output array sequential|[reverse|right] character ( len =* ), optional , intent ( in ) :: nulls !! return strings composed of delimiters or not ignore|return|ignoreend character ( len = :), allocatable , intent ( out ) :: array (:) !! output array of tokens integer :: n ! max number of strings INPUT_LINE could split into if all delimiter integer , allocatable :: ibegin (:) ! positions in input string where tokens start integer , allocatable :: iterm (:) ! positions in input string where tokens end character ( len = :), allocatable :: dlim ! string containing delimiter characters character ( len = :), allocatable :: ordr ! string containing order keyword character ( len = :), allocatable :: nlls ! string containing nulls keyword integer :: ii , iiii ! loop parameters used to control print order integer :: icount ! number of tokens found integer :: ilen ! length of input string with trailing spaces trimmed integer :: i10 , i20 , i30 ! loop counters integer :: icol ! pointer into input string as it is being parsed integer :: idlim ! number of delimiter characters integer :: ifound ! where next delimiter character is found in remaining input string data integer :: inotnull ! count strings not composed of delimiters integer :: ireturn ! number of tokens returned integer :: imax ! length of longest token ! decide on value for optional DELIMITERS parameter if ( present ( delimiters )) then ! optional delimiter list was present if ( delimiters /= '' ) then ! if DELIMITERS was specified and not null use it dlim = delimiters else ! DELIMITERS was specified on call as empty string dlim = ' ' // char ( 9 ) // char ( 10 ) // char ( 11 ) // char ( 12 ) // char ( 13 ) // char ( 0 ) ! use default delimiter when not specified endif else ! no delimiter value was specified dlim = ' ' // char ( 9 ) // char ( 10 ) // char ( 11 ) // char ( 12 ) // char ( 13 ) // char ( 0 ) ! use default delimiter when not specified endif idlim = len ( dlim ) ! dlim a lot of blanks on some machines if dlim is a big string if ( present ( order )) then ; ordr = lower ( adjustl ( order )); else ; ordr = 'sequential' ; endif ! decide on value for optional ORDER parameter if ( present ( nulls )) then ; nlls = lower ( adjustl ( nulls )); else ; nlls = 'ignore' ; endif ! optional parameter n = len ( input_line ) + 1 ! max number of strings INPUT_LINE could split into if all delimiter allocate ( ibegin ( n )) ! allocate enough space to hold starting location of tokens if string all tokens allocate ( iterm ( n )) ! allocate enough space to hold ending location of tokens if string all tokens ibegin (:) = 1 iterm (:) = 1 ilen = len ( input_line ) ! ILEN is the column position of the last non-blank character icount = 0 ! how many tokens found inotnull = 0 ! how many tokens found not composed of delimiters imax = 0 ! length of longest token found select case ( ilen ) case ( 0 ) ! command was totally blank case default ! there is at least one non-delimiter in INPUT_LINE if get here icol = 1 ! initialize pointer into input line INFINITE : do i30 = 1 , ilen , 1 ! store into each array element ibegin ( i30 ) = icol ! assume start new token on the character if ( index ( dlim ( 1 : idlim ), input_line ( icol : icol )) == 0 ) then ! if current character is not a delimiter iterm ( i30 ) = ilen ! initially assume no more tokens do i10 = 1 , idlim ! search for next delimiter ifound = index ( input_line ( ibegin ( i30 ): ilen ), dlim ( i10 : i10 )) IF ( ifound > 0 ) then iterm ( i30 ) = min ( iterm ( i30 ), ifound + ibegin ( i30 ) - 2 ) endif enddo icol = iterm ( i30 ) + 2 ! next place to look as found end of this token inotnull = inotnull + 1 ! increment count of number of tokens not composed of delimiters else ! character is a delimiter for a null string iterm ( i30 ) = icol - 1 ! record assumed end of string. Will be less than beginning icol = icol + 1 ! advance pointer into input string endif imax = max ( imax , iterm ( i30 ) - ibegin ( i30 ) + 1 ) icount = i30 ! increment count of number of tokens found if ( icol > ilen ) then ! no text left exit INFINITE endif enddo INFINITE end select select case ( trim ( adjustl ( nlls ))) case ( 'ignore' , '' , 'ignoreend' ) ireturn = inotnull case default ireturn = icount end select allocate ( character ( len = imax ) :: array ( ireturn )) ! allocate the array to return !allocate(array(ireturn)) ! allocate the array to turn select case ( trim ( adjustl ( ordr ))) ! decide which order to store tokens case ( 'reverse' , 'right' ) ; ii = ireturn ; iiii =- 1 ! last to first case default ; ii = 1 ; iiii = 1 ! first to last end select do i20 = 1 , icount ! fill the array with the tokens that were found if ( iterm ( i20 ) < ibegin ( i20 )) then select case ( trim ( adjustl ( nlls ))) case ( 'ignore' , '' , 'ignoreend' ) case default array ( ii ) = ' ' ii = ii + iiii end select else array ( ii ) = input_line ( ibegin ( i20 ): iterm ( i20 )) ii = ii + iiii endif enddo end subroutine split !! Author: Milan Curcic !! Computes the first and last indices of tokens in input string, delimited !! by the characters in set, and stores them into first and last output !! arrays. pure subroutine split_first_last ( string , set , first , last ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: set integer , allocatable , intent ( out ) :: first (:) integer , allocatable , intent ( out ) :: last (:) integer , dimension ( len ( string ) + 1 ) :: istart , iend integer :: p , n , slen slen = len ( string ) n = 0 if ( slen > 0 ) then p = 0 do while ( p < slen ) n = n + 1 istart ( n ) = min ( p + 1 , slen ) call split_pos ( string , set , p ) iend ( n ) = p - 1 end do end if first = istart (: n ) last = iend (: n ) end subroutine split_first_last !! Author: Milan Curcic !! If back is absent, computes the leftmost token delimiter in string whose !! position is > pos. If back is present and true, computes the rightmost !! token delimiter in string whose position is < pos. The result is stored !! in pos. pure subroutine split_pos ( string , set , pos , back ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: set integer , intent ( in out ) :: pos logical , intent ( in ), optional :: back logical :: backward integer :: result_pos , bound if ( len ( string ) == 0 ) then pos = 1 return end if !TODO use optval when implemented in stdlib !backward = optval(back, .false.) backward = . false . if ( present ( back )) backward = back if ( backward ) then bound = min ( len ( string ), max ( pos - 1 , 0 )) result_pos = scan ( string (: bound ), set , back = . true .) else result_pos = scan ( string ( min ( pos + 1 , len ( string )):), set ) + pos if ( result_pos < pos + 1 ) result_pos = len ( string ) + 1 end if pos = result_pos end subroutine split_pos !> Returns string with characters in charset replaced with target_char. pure function replace ( string , charset , target_char ) result ( res ) character ( * ), intent ( in ) :: string character , intent ( in ) :: charset (:), target_char character ( len ( string )) :: res integer :: n res = string do n = 1 , len ( string ) if ( any ( string ( n : n ) == charset )) then res ( n : n ) = target_char end if end do end function replace !> increase the size of a TYPE(STRING_T) array by N elements subroutine resize_string ( list , n ) !> Instance of the array to be resized type ( string_t ), allocatable , intent ( inout ) :: list (:) !> Dimension of the final array size integer , intent ( in ), optional :: n type ( string_t ), allocatable :: tmp (:) integer :: this_size , new_size , i integer , parameter :: initial_size = 16 if ( allocated ( list )) then this_size = size ( list , 1 ) call move_alloc ( list , tmp ) else this_size = initial_size end if if ( present ( n )) then new_size = n else new_size = this_size + this_size / 2 + 1 end if allocate ( list ( new_size )) if ( allocated ( tmp )) then this_size = min ( size ( tmp , 1 ), size ( list , 1 )) do i = 1 , this_size call move_alloc ( tmp ( i )% s , list ( i )% s ) end do deallocate ( tmp ) end if end subroutine resize_string !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!##NAME !! join(3f) - [M_strings:EDITING] append CHARACTER variable array into !! a single CHARACTER variable with specified separator !! (LICENSE:PD) !! !!##SYNOPSIS !! !! pure function join(str,sep,trm,left,right,start,end) result (string) !! !! character(len=*),intent(in) :: str(:) !! character(len=*),intent(in),optional :: sep !! logical,intent(in),optional :: trm !! character(len=*),intent(in),optional :: right !! character(len=*),intent(in),optional :: left !! character(len=*),intent(in),optional :: start !! character(len=*),intent(in),optional :: end !! character(len=:),allocatable :: string !! !!##DESCRIPTION !! JOIN(3f) appends the elements of a CHARACTER array into a single !! CHARACTER variable, with elements 1 to N joined from left to right. !! By default each element is trimmed of trailing spaces and the !! default separator is a null string. !! !!##OPTIONS !! STR(:) array of CHARACTER variables to be joined !! SEP separator string to place between each variable. defaults !! to a null string. !! LEFT string to place at left of each element !! RIGHT string to place at right of each element !! START prefix string !! END suffix string !! TRM option to trim each element of STR of trailing !! spaces. Defaults to .TRUE. !! !!##RESULT !! STRING CHARACTER variable composed of all of the elements of STR() !! appended together with the optional separator SEP placed !! between the elements. !! !!##EXAMPLE !! !! Sample program: !! !! program demo_join !! use M_strings, only: join !! implicit none !! character(len=:),allocatable :: s(:) !! character(len=:),allocatable :: out !! integer :: i !! s=[character(len=10) :: 'United',' we',' stand,', & !! & ' divided',' we fall.'] !! out=join(s) !! write(*,'(a)') out !! write(*,'(a)') join(s,trm=.false.) !! write(*,'(a)') (join(s,trm=.false.,sep='|'),i=1,3) !! write(*,'(a)') join(s,sep='<>') !! write(*,'(a)') join(s,sep=';',left='[',right=']') !! write(*,'(a)') join(s,left='[',right=']') !! write(*,'(a)') join(s,left='>>') !! end program demo_join !! !! Expected output: !! !! United we stand, divided we fall. !! United we stand, divided we fall. !! United | we | stand, | divided | we fall. !! United | we | stand, | divided | we fall. !! United | we | stand, | divided | we fall. !! United<> we<> stand,<> divided<> we fall. !! [United];[ we];[ stand,];[ divided];[ we fall.] !! [United][ we][ stand,][ divided][ we fall.] !! >>United>> we>> stand,>> divided>> we fall. pure function join ( str , sep , trm , left , right , start , end ) result ( string ) ! @(#)M_strings::join(3f): merge string array into a single CHARACTER value adding specified separators, caps, prefix and suffix character ( len =* ), intent ( in ) :: str (:) character ( len =* ), intent ( in ), optional :: sep , right , left , start , end logical , intent ( in ), optional :: trm character ( len = :), allocatable :: sep_local , left_local , right_local character ( len = :), allocatable :: string logical :: trm_local integer :: i if ( present ( sep )) then ; sep_local = sep ; else ; sep_local = '' ; endif if ( present ( trm )) then ; trm_local = trm ; else ; trm_local = . true . ; endif if ( present ( left )) then ; left_local = left ; else ; left_local = '' ; endif if ( present ( right )) then ; right_local = right ; else ; right_local = '' ; endif string = '' if ( size ( str ) == 0 ) then string = string // left_local // right_local else do i = 1 , size ( str ) - 1 if ( trm_local ) then string = string // left_local // trim ( str ( i )) // right_local // sep_local else string = string // left_local // str ( i ) // right_local // sep_local endif enddo if ( trm_local ) then string = string // left_local // trim ( str ( i )) // right_local else string = string // left_local // str ( i ) // right_local endif endif if ( present ( start )) string = start // string if ( present ( end )) string = string // end end function join !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!## NAME !! glob(3f) - [fpm_strings:COMPARE] compare given string for match to !! pattern which may contain wildcard characters !! (LICENSE:PD) !! !!## SYNOPSIS !! !! logical function glob(string, pattern ) !! !! character(len=*),intent(in) :: string !! character(len=*),intent(in) :: pattern !! !!## DESCRIPTION !! glob(3f) compares given STRING for match to PATTERN which may !! contain wildcard characters. !! !! In this version to get a match the entire string must be described !! by PATTERN. Trailing whitespace is significant, so trim the input !! string to have trailing whitespace ignored. !! !!## OPTIONS !! string the input string to test to see if it contains the pattern. !! pattern the following simple globbing options are available !! !! o \"?\" matching any one character !! o \"*\" matching zero or more characters. !! Do NOT use adjacent asterisks. !! o Both strings may have trailing spaces which !! are ignored. !! o There is no escape character, so matching strings with !! literal question mark and asterisk is problematic. !! !!## EXAMPLES !! !! Example program !! !! program demo_glob !! implicit none !! ! This main() routine passes a bunch of test strings !! ! into the above code. In performance comparison mode, !! ! it does that over and over. Otherwise, it does it just !! ! once. Either way, it outputs a passed/failed result. !! ! !! integer :: nReps !! logical :: allpassed !! integer :: i !! allpassed = .true. !! !! nReps = 10000 !! ! Can choose as many repetitions as you're expecting !! ! in the real world. !! nReps = 1 !! !! do i=1,nReps !! ! Cases with repeating character sequences. !! allpassed=allpassed .and. test(\"a*abab\", \"a*b\", .true.) !! !!cycle !! allpassed=allpassed .and. test(\"ab\", \"*?\", .true.) !! allpassed=allpassed .and. test(\"abc\", \"*?\", .true.) !! allpassed=allpassed .and. test(\"abcccd\", \"*ccd\", .true.) !! allpassed=allpassed .and. test(\"bLah\", \"bLaH\", .false.) !! allpassed=allpassed .and. test(\"mississippi\", \"*sip*\", .true.) !! allpassed=allpassed .and. & !! & test(\"xxxx*zzzzzzzzy*f\", \"xxx*zzy*f\", .true.) !! allpassed=allpassed .and. & !! & test(\"xxxx*zzzzzzzzy*f\", \"xxxx*zzy*fffff\", .false.) !! allpassed=allpassed .and. & !! & test(\"mississipissippi\", \"*issip*ss*\", .true.) !! allpassed=allpassed .and. & !! & test(\"xxxxzzzzzzzzyf\", \"xxxx*zzy*fffff\", .false.) !! allpassed=allpassed .and. & !! & test(\"xxxxzzzzzzzzyf\", \"xxxx*zzy*f\", .true.) !! allpassed=allpassed .and. test(\"xyxyxyzyxyz\", \"xy*z*xyz\", .true.) !! allpassed=allpassed .and. test(\"xyxyxyxyz\", \"xy*xyz\", .true.) !! allpassed=allpassed .and. test(\"mississippi\", \"mi*sip*\", .true.) !! allpassed=allpassed .and. test(\"ababac\", \"*abac*\", .true.) !! allpassed=allpassed .and. test(\"aaazz\", \"a*zz*\", .true.) !! allpassed=allpassed .and. test(\"a12b12\", \"*12*23\", .false.) !! allpassed=allpassed .and. test(\"a12b12\", \"a12b\", .false.) !! allpassed=allpassed .and. test(\"a12b12\", \"*12*12*\", .true.) !! !! ! Additional cases where the '*' char appears in the tame string. !! allpassed=allpassed .and. test(\"*\", \"*\", .true.) !! allpassed=allpassed .and. test(\"a*r\", \"a*\", .true.) !! allpassed=allpassed .and. test(\"a*ar\", \"a*aar\", .false.) !! !! ! More double wildcard scenarios. !! allpassed=allpassed .and. test(\"XYXYXYZYXYz\", \"XY*Z*XYz\", .true.) !! allpassed=allpassed .and. test(\"missisSIPpi\", \"*SIP*\", .true.) !! allpassed=allpassed .and. test(\"mississipPI\", \"*issip*PI\", .true.) !! allpassed=allpassed .and. test(\"xyxyxyxyz\", \"xy*xyz\", .true.) !! allpassed=allpassed .and. test(\"miSsissippi\", \"mi*sip*\", .true.) !! allpassed=allpassed .and. test(\"miSsissippi\", \"mi*Sip*\", .false.) !! allpassed=allpassed .and. test(\"abAbac\", \"*Abac*\", .true.) !! allpassed=allpassed .and. test(\"aAazz\", \"a*zz*\", .true.) !! allpassed=allpassed .and. test(\"A12b12\", \"*12*23\", .false.) !! allpassed=allpassed .and. test(\"a12B12\", \"*12*12*\", .true.) !! allpassed=allpassed .and. test(\"oWn\", \"*oWn*\", .true.) !! !! ! Completely tame (no wildcards) cases. !! allpassed=allpassed .and. test(\"bLah\", \"bLah\", .true.) !! !! ! Simple mixed wildcard tests suggested by IBMer Marlin Deckert. !! allpassed=allpassed .and. test(\"a\", \"*?\", .true.) !! !! ! More mixed wildcard tests including coverage for false positives. !! allpassed=allpassed .and. test(\"a\", \"??\", .false.) !! allpassed=allpassed .and. test(\"ab\", \"?*?\", .true.) !! allpassed=allpassed .and. test(\"ab\", \"*?*?*\", .true.) !! allpassed=allpassed .and. test(\"abc\", \"?**?*?\", .true.) !! allpassed=allpassed .and. test(\"abc\", \"?**?*&?\", .false.) !! allpassed=allpassed .and. test(\"abcd\", \"?b*??\", .true.) !! allpassed=allpassed .and. test(\"abcd\", \"?a*??\", .false.) !! allpassed=allpassed .and. test(\"abcd\", \"?**?c?\", .true.) !! allpassed=allpassed .and. test(\"abcd\", \"?**?d?\", .false.) !! allpassed=allpassed .and. test(\"abcde\", \"?*b*?*d*?\", .true.) !! !! ! Single-character-match cases. !! allpassed=allpassed .and. test(\"bLah\", \"bL?h\", .true.) !! allpassed=allpassed .and. test(\"bLaaa\", \"bLa?\", .false.) !! allpassed=allpassed .and. test(\"bLah\", \"bLa?\", .true.) !! allpassed=allpassed .and. test(\"bLaH\", \"?Lah\", .false.) !! allpassed=allpassed .and. test(\"bLaH\", \"?LaH\", .true.) !! !! ! Many-wildcard scenarios. !! allpassed=allpassed .and. test(& !! &\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa& !! &aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab\",& !! &\"a*a*a*a*a*a*aa*aaa*a*a*b\",& !! &.true.) !! allpassed=allpassed .and. test(& !! &\"abababababababababababababababababababaacacacacacacac& !! &adaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\",& !! &\"*a*b*ba*ca*a*aa*aaa*fa*ga*b*\",& !! &.true.) !! allpassed=allpassed .and. test(& !! &\"abababababababababababababababababababaacacacacacaca& !! &cadaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\",& !! &\"*a*b*ba*ca*a*x*aaa*fa*ga*b*\",& !! &.false.) !! allpassed=allpassed .and. test(& !! &\"abababababababababababababababababababaacacacacacacacad& !! &aeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\",& !! &\"*a*b*ba*ca*aaaa*fa*ga*gggg*b*\",& !! &.false.) !! allpassed=allpassed .and. test(& !! &\"abababababababababababababababababababaacacacacacacacad& !! &aeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\",& !! &\"*a*b*ba*ca*aaaa*fa*ga*ggg*b*\",& !! &.true.) !! allpassed=allpassed .and. test(\"aaabbaabbaab\", \"*aabbaa*a*\", .true.) !! allpassed=allpassed .and. & !! test(\"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\",& !! &\"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\", .true.) !! allpassed=allpassed .and. test(\"aaaaaaaaaaaaaaaaa\",& !! &\"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\", .true.) !! allpassed=allpassed .and. test(\"aaaaaaaaaaaaaaaa\",& !! &\"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\", .false.) !! allpassed=allpassed .and. test(& !! &\"abc*abcd*abcde*abcdef*abcdefg*abcdefgh*abcdefghi*abcdefghij& !! &*abcdefghijk*abcdefghijkl*abcdefghijklm*abcdefghijklmn\",& !! & \"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc& !! &*abc*abc*abc*\",& !! &.false.) !! allpassed=allpassed .and. test(& !! &\"abc*abcd*abcde*abcdef*abcdefg*abcdefgh*abcdefghi*abcdefghij& !! &*abcdefghijk*abcdefghijkl*abcdefghijklm*abcdefghijklmn\",& !! &\"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*\",& !! &.true.) !! allpassed=allpassed .and. test(\"abc*abcd*abcd*abc*abcd\",& !! &\"abc*abc*abc*abc*abc\", .false.) !! allpassed=allpassed .and. test( \"abc*abcd*abcd*abc*abcd*abcd& !! &*abc*abcd*abc*abc*abcd\", & !! &\"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abcd\",& !! &.true.) !! allpassed=allpassed .and. test(\"abc\",& !! &\"********a********b********c********\", .true.) !! allpassed=allpassed .and.& !! &test(\"********a********b********c********\", \"abc\", .false.) !! allpassed=allpassed .and. & !! &test(\"abc\", \"********a********b********b********\", .false.) !! allpassed=allpassed .and. test(\"*abc*\", \"***a*b*c***\", .true.) !! !! ! A case-insensitive algorithm test. !! ! allpassed=allpassed .and. test(\"mississippi\", \"*issip*PI\", .true.) !! enddo !! !! if (allpassed)then !! write(*,'(a)')\"Passed\",nReps !! else !! write(*,'(a)')\"Failed\" !! endif !! contains !! ! This is a test program for wildcard matching routines. !! ! It can be used either to test a single routine for correctness, !! ! or to compare the timings of two (or more) different wildcard !! ! matching routines. !! ! !! function test(tame, wild, bExpectedResult) result(bpassed) !! use fpm_strings, only : glob !! character(len=*) :: tame !! character(len=*) :: wild !! logical :: bExpectedResult !! logical :: bResult !! logical :: bPassed !! bResult = .true. ! We'll do \"&=\" cumulative checking. !! bPassed = .false. ! Assume the worst. !! write(*,*)repeat('=',79) !! bResult = glob(tame, wild) ! Call a wildcard matching routine. !! !! ! To assist correctness checking, output the two strings in any !! ! failing scenarios. !! if (bExpectedResult .eqv. bResult) then !! bPassed = .true. !! if(nReps == 1) write(*,*)\"Passed match on \",tame,\" vs. \", wild !! else !! if(nReps == 1) write(*,*)\"Failed match on \",tame,\" vs. \", wild !! endif !! !! end function test !! end program demo_glob !! !! Expected output !! !! !!## REFERENCE !! The article \"Matching Wildcards: An Empirical Way to Tame an Algorithm\" !! in Dr Dobb's Journal, By Kirk J. Krauss, October 07, 2014 !! function glob ( tame , wild ) ! @(#)fpm_strings::glob(3f): function compares text strings, one of which can have wildcards ('*' or '?'). logical :: glob !! result of test character ( len =* ) :: tame !! A string without wildcards to compare to the globbing expression character ( len =* ) :: wild !! A (potentially) corresponding string with wildcards character ( len = len ( tame ) + 1 ) :: tametext character ( len = len ( wild ) + 1 ) :: wildtext character ( len = 1 ), parameter :: NULL = char ( 0 ) integer :: wlen integer :: ti , wi integer :: i character ( len = :), allocatable :: tbookmark , wbookmark ! These two values are set when we observe a wildcard character. They ! represent the locations, in the two strings, from which we start once we've observed it. tametext = tame // NULL wildtext = wild // NULL tbookmark = NULL wbookmark = NULL wlen = len ( wild ) wi = 1 ti = 1 do ! Walk the text strings one character at a time. if ( wildtext ( wi : wi ) == '*' ) then ! How do you match a unique text string? do i = wi , wlen ! Easy: unique up on it! if ( wildtext ( wi : wi ) == '*' ) then wi = wi + 1 else exit endif enddo if ( wildtext ( wi : wi ) == NULL ) then ! \"x\" matches \"*\" glob = . true . return endif if ( wildtext ( wi : wi ) /= '?' ) then ! Fast-forward to next possible match. do while ( tametext ( ti : ti ) /= wildtext ( wi : wi )) ti = ti + 1 if ( tametext ( ti : ti ) == NULL ) then glob = . false . return ! \"x\" doesn't match \"*y*\" endif enddo endif wbookmark = wildtext ( wi :) tbookmark = tametext ( ti :) elseif ( tametext ( ti : ti ) /= wildtext ( wi : wi ) . and . wildtext ( wi : wi ) /= '?' ) then ! Got a non-match. If we've set our bookmarks, back up to one or both of them and retry. if ( wbookmark /= NULL ) then if ( wildtext ( wi :) /= wbookmark ) then wildtext = wbookmark ; wlen = len_trim ( wbookmark ) wi = 1 ! Don't go this far back again. if ( tametext ( ti : ti ) /= wildtext ( wi : wi )) then tbookmark = tbookmark ( 2 :) tametext = tbookmark ti = 1 cycle ! \"xy\" matches \"*y\" else wi = wi + 1 endif endif if ( tametext ( ti : ti ) /= NULL ) then ti = ti + 1 cycle ! \"mississippi\" matches \"*sip*\" endif endif glob = . false . return ! \"xy\" doesn't match \"x\" endif ti = ti + 1 wi = wi + 1 if ( tametext ( ti : ti ) == NULL ) then ! How do you match a tame text string? if ( wildtext ( wi : wi ) /= NULL ) then do while ( wildtext ( wi : wi ) == '*' ) ! The tame way: unique up on it! wi = wi + 1 ! \"x\" matches \"x*\" if ( wildtext ( wi : wi ) == NULL ) exit enddo endif if ( wildtext ( wi : wi ) == NULL ) then glob = . true . return ! \"x\" matches \"x\" endif glob = . false . return ! \"x\" doesn't match \"xy\" endif enddo end function glob !> Returns the length of the string representation of 'i' pure integer function str_int_len ( i ) result ( sz ) integer , intent ( in ) :: i integer , parameter :: MAX_STR = 100 character ( MAX_STR ) :: s ! If 's' is too short (MAX_STR too small), Fortran will abort with: ! \"Fortran runtime error: End of record\" write ( s , '(i0)' ) i sz = len_trim ( s ) end function !> Converts integer \"i\" to string pure function str_int ( i ) result ( s ) integer , intent ( in ) :: i character ( len = str_int_len ( i )) :: s write ( s , '(i0)' ) i end function !> Returns the length of the string representation of 'i' pure integer function str_int64_len ( i ) result ( sz ) integer ( int64 ), intent ( in ) :: i integer , parameter :: MAX_STR = 100 character ( MAX_STR ) :: s ! If 's' is too short (MAX_STR too small), Fortran will abort with: ! \"Fortran runtime error: End of record\" write ( s , '(i0)' ) i sz = len_trim ( s ) end function !> Converts integer \"i\" to string pure function str_int64 ( i ) result ( s ) integer ( int64 ), intent ( in ) :: i character ( len = str_int64_len ( i )) :: s write ( s , '(i0)' ) i end function !> Returns the length of the string representation of 'l' pure integer function str_logical_len ( l ) result ( sz ) logical , intent ( in ) :: l if ( l ) then sz = 6 else sz = 7 end if end function !> Converts logical \"l\" to string pure function str_logical ( l ) result ( s ) logical , intent ( in ) :: l character ( len = str_logical_len ( l )) :: s if ( l ) then s = \".true.\" else s = \".false.\" end if end function !> Returns string with special characters replaced with an underscore. !! For now, only a hyphen is treated as a special character, but this can be !! expanded to other characters if needed. pure function to_fortran_name ( string ) result ( res ) character ( * ), intent ( in ) :: string character ( len ( string )) :: res character , parameter :: SPECIAL_CHARACTERS ( * ) = [ '-' ] res = replace ( string , SPECIAL_CHARACTERS , '_' ) end function to_fortran_name elemental function is_fortran_name ( line ) result ( lout ) ! determine if a string is a valid Fortran name ignoring trailing spaces ! (but not leading spaces) character ( len =* ), parameter :: int = '0123456789' character ( len =* ), parameter :: lower = 'abcdefghijklmnopqrstuvwxyz' character ( len =* ), parameter :: upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' character ( len =* ), parameter :: allowed = upper // lower // int // '_' character ( len =* ), intent ( in ) :: line character ( len = :), allocatable :: name logical :: lout name = trim ( line ) if ( len ( name ) /= 0 ) then lout = . true . & & . and . verify ( name ( 1 : 1 ), lower // upper ) == 0 & & . and . verify ( name , allowed ) == 0 & & . and . len ( name ) <= 63 else lout = . false . endif end function is_fortran_name !> Check that a module name fits the current naming rules: !> 1) It must be a valid FORTRAN name (<=63 chars, begin with letter, \"_\" is only allowed non-alphanumeric) !> 2) It must begin with the package name !> 3) If longer, package name must be followed by default separator plus at least one char logical function is_valid_module_name ( module_name , package_name , custom_prefix , enforce_module_names ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: package_name type ( string_t ), intent ( in ) :: custom_prefix logical , intent ( in ) :: enforce_module_names !> Basic check: check the name is Fortran-compliant valid = is_fortran_name ( module_name % s ); if (. not . valid ) return !> FPM package enforcing: check that the module name begins with the package name if ( enforce_module_names ) then ! Default prefixing is always valid valid = has_valid_standard_prefix ( module_name , package_name ) ! If a custom prefix was validated, it provides additional naming options ! Because they never overlap with the default prefix, the former is always an option if ( len_trim ( custom_prefix ) > 0 . and . . not . valid ) & valid = has_valid_custom_prefix ( module_name , custom_prefix ) end if end function is_valid_module_name !> Check that a custom module prefix fits the current naming rules: !> 1) Only alphanumeric characters (no spaces, dashes, underscores or other characters) !> 2) Does not begin with a number (Fortran-compatible syntax) logical function is_valid_module_prefix ( module_prefix ) result ( valid ) type ( string_t ), intent ( in ) :: module_prefix character ( len =* ), parameter :: num = '0123456789' character ( len =* ), parameter :: lower = 'abcdefghijklmnopqrstuvwxyz' character ( len =* ), parameter :: upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' character ( len =* ), parameter :: alpha = upper // lower character ( len =* ), parameter :: allowed = alpha // num character ( len = :), allocatable :: name name = trim ( module_prefix % s ) if ( len ( name ) > 0 . and . len ( name ) <= 63 ) then valid = verify ( name ( 1 : 1 ), alpha ) == 0 . and . & verify ( name , allowed ) == 0 else valid = . false . endif end function is_valid_module_prefix type ( string_t ) function module_prefix_template ( project_name , custom_prefix ) result ( prefix ) type ( string_t ), intent ( in ) :: project_name type ( string_t ), intent ( in ) :: custom_prefix if ( is_valid_module_prefix ( custom_prefix )) then prefix = string_t ( trim ( custom_prefix % s ) // \"_\" ) else prefix = string_t ( to_fortran_name ( project_name % s ) // \"__\" ) end if end function module_prefix_template type ( string_t ) function module_prefix_type ( project_name , custom_prefix ) result ( ptype ) type ( string_t ), intent ( in ) :: project_name type ( string_t ), intent ( in ) :: custom_prefix if ( is_valid_module_prefix ( custom_prefix )) then ptype = string_t ( \"custom\" ) else ptype = string_t ( \"default\" ) end if end function module_prefix_type !> Check that a module name is prefixed with a custom prefix: !> 1) It must be a valid FORTRAN name subset (<=63 chars, begin with letter, only alphanumeric allowed) !> 2) It must begin with the prefix !> 3) If longer, package name must be followed by default separator (\"_\") plus at least one char logical function has_valid_custom_prefix ( module_name , custom_prefix ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: custom_prefix !> custom_module separator: single underscore character ( * ), parameter :: SEP = \"_\" logical :: is_same , has_separator , same_beginning integer :: lpkg , lmod , lsep !> Basic check: check that both names are individually valid valid = is_fortran_name ( module_name % s ) . and . & is_valid_module_prefix ( custom_prefix ) !> FPM package enforcing: check that the module name begins with the custom prefix if ( valid ) then !> Query string lengths lpkg = len_trim ( custom_prefix ) lmod = len_trim ( module_name ) lsep = len_trim ( SEP ) same_beginning = str_begins_with_str ( module_name % s , custom_prefix % s , case_sensitive = . false .) is_same = lpkg == lmod . and . same_beginning if ( lmod >= lpkg + lsep ) then has_separator = str_begins_with_str ( module_name % s ( lpkg + 1 : lpkg + lsep ), SEP ) else has_separator = . false . endif !> 2) It must begin with the package name. !> 3) It can be equal to the package name, or, if longer, must be followed by the ! default separator plus at least one character !> 4) Package name must not end with an underscore valid = same_beginning . and . ( is_same . or . ( lmod > lpkg + lsep . and . has_separator )) end if end function has_valid_custom_prefix !> Check that a module name is prefixed with the default package prefix: !> 1) It must be a valid FORTRAN name (<=63 chars, begin with letter, \"_\" is only allowed non-alphanumeric) !> 2) It must begin with the package name !> 3) If longer, package name must be followed by default separator plus at least one char logical function has_valid_standard_prefix ( module_name , package_name ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: package_name !> Default package__module separator: two underscores character ( * ), parameter :: SEP = \"__\" character ( len = :), allocatable :: fortranized_pkg logical :: is_same , has_separator , same_beginning integer :: lpkg , lmod , lsep !> Basic check: check the name is Fortran-compliant valid = is_fortran_name ( module_name % s ) !> FPM package enforcing: check that the module name begins with the package name if ( valid ) then fortranized_pkg = to_fortran_name ( package_name % s ) !> Query string lengths lpkg = len_trim ( fortranized_pkg ) lmod = len_trim ( module_name ) lsep = len_trim ( SEP ) same_beginning = str_begins_with_str ( module_name % s , fortranized_pkg , case_sensitive = . false .) is_same = lpkg == lmod . and . same_beginning if ( lmod >= lpkg + lsep ) then has_separator = str_begins_with_str ( module_name % s ( lpkg + 1 : lpkg + lsep ), SEP ) else has_separator = . false . endif !> 2) It must begin with the package name. !> 3) It can be equal to the package name, or, if longer, must be followed by the ! default separator plus at least one character !> 4) Package name must not end with an underscore valid = is_fortran_name ( fortranized_pkg ) . and . & fortranized_pkg ( lpkg : lpkg ) /= '_' . and . & ( same_beginning . and . ( is_same . or . ( lmod > lpkg + lsep . and . has_separator ))) end if end function has_valid_standard_prefix !> Check that two string _objects_ are exactly identical pure logical function string_is_same ( this , that ) !> two strings to be compared type ( string_t ), intent ( in ) :: this , that integer :: i string_is_same = . false . if ( allocated ( this % s ). neqv . allocated ( that % s )) return if ( allocated ( this % s )) then if (. not . len ( this % s ) == len ( that % s )) return if (. not . len_trim ( this % s ) == len_trim ( that % s )) return do i = 1 , len_trim ( this % s ) if (. not .( this % s ( i : i ) == that % s ( i : i ))) return end do end if ! All checks passed string_is_same = . true . end function string_is_same !> Check that two allocatable string _object_ arrays are exactly identical pure logical function string_arrays_same ( this , that ) !> two string arrays to be compared type ( string_t ), allocatable , intent ( in ) :: this (:), that (:) integer :: i string_arrays_same = . false . if ( allocated ( this ). neqv . allocated ( that )) return if ( allocated ( this )) then if (. not .( size ( this ) == size ( that ))) return if (. not .( ubound ( this , 1 ) == ubound ( that , 1 ))) return if (. not .( lbound ( this , 1 ) == lbound ( that , 1 ))) return do i = lbound ( this , 1 ), ubound ( this , 1 ) if (. not . string_is_same ( this ( i ), that ( i ))) return end do end if ! All checks passed string_arrays_same = . true . end function string_arrays_same ! Remove all characters from a set from a string subroutine remove_characters_in_set ( string , set , replace_with ) character ( len = :), allocatable , intent ( inout ) :: string character ( * ), intent ( in ) :: set character , optional , intent ( in ) :: replace_with ! Replace with this character instead of removing integer :: feed , length if (. not . allocated ( string )) return if ( len ( set ) <= 0 ) return length = len ( string ) feed = scan ( string , set ) do while ( length > 0 . and . feed > 0 ) ! Remove heading if ( length == 1 ) then string = \"\" elseif ( feed == 1 ) then string = string ( 2 : length ) ! Remove trailing elseif ( feed == length ) then string = string ( 1 : length - 1 ) ! In between: replace with given character elseif ( present ( replace_with )) then string ( feed : feed ) = replace_with ! Or just remove else string = string ( 1 : feed - 1 ) // string ( feed + 1 : length ) end if length = len ( string ) feed = scan ( string , set ) end do end subroutine remove_characters_in_set ! Remove all new line characters from the current string, replace them with spaces subroutine remove_newline_characters ( string ) type ( string_t ), intent ( inout ) :: string integer :: feed , length character ( * ), parameter :: CRLF = achar ( 13 ) // new_line ( 'a' ) character ( * ), parameter :: SPACE = ' ' call remove_characters_in_set ( string % s , set = CRLF , replace_with = SPACE ) end subroutine remove_newline_characters !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!### NAME !! notabs(3f) - [fpm_strings:NONALPHA] expand tab characters !! (LICENSE:PD) !! !!### SYNOPSIS !! !! subroutine notabs(INSTR,OUTSTR,ILEN) !! !! character(len=*),intent=(in) :: INSTR !! character(len=*),intent=(out) :: OUTSTR !! integer,intent=(out) :: ILEN !! !!### DESCRIPTION !! NOTABS() converts tabs in INSTR to spaces in OUTSTR while maintaining !! columns. It assumes a tab is set every 8 characters. Trailing spaces !! are removed. !! !! In addition, trailing carriage returns and line feeds are removed !! (they are usually a problem created by going to and from MSWindows). !! !! What are some reasons for removing tab characters from an input line? !! Some Fortran compilers have problems with tabs, as tabs are not !! part of the Fortran character set. Some editors and printers will !! have problems with tabs. It is often useful to expand tabs in input !! files to simplify further processing such as tokenizing an input line. !! !!### OPTIONS !! instr Input line to remove tabs from !! !!### RESULTS !! outstr Output string with tabs expanded. Assumed to be of sufficient !! length !! ilen Significant length of returned string !! !!### EXAMPLES !! !! Sample program: !! !! program demo_notabs !! !! ! test filter to remove tabs and trailing white space from input !! ! on files up to 1024 characters wide !! use fpm_strings, only : notabs !! character(len=1024) :: in,out !! integer :: ios,iout !! do !! read(*,'(A)',iostat=ios)in !! if(ios /= 0) exit !! call notabs(in,out,iout) !! write(*,'(a)')out(:iout) !! enddo !! end program demo_notabs !! !!### SEE ALSO !! GNU/Unix commands expand(1) and unexpand(1) !! elemental impure subroutine notabs ( instr , outstr , ilen ) ! ident_31=\"@(#)fpm_strings::notabs(3f): convert tabs to spaces while maintaining columns, remove CRLF chars\" character ( len =* ), intent ( in ) :: instr ! input line to scan for tab characters character ( len =* ), intent ( out ) :: outstr ! tab-expanded version of INSTR produced integer , intent ( out ) :: ilen ! column position of last character put into output string ! that is, ILEN holds the position of the last non-blank character in OUTSTR integer , parameter :: tabsize = 8 ! assume a tab stop is set every 8th column integer :: ipos ! position in OUTSTR to put next character of INSTR integer :: lenin ! length of input string trimmed of trailing spaces integer :: lenout ! number of characters output string can hold integer :: istep ! counter that advances thru input string INSTR one character at a time character ( len = 1 ) :: c ! character in input line being processed integer :: iade ! ADE (ASCII Decimal Equivalent) of character being tested ipos = 1 ! where to put next character in output string OUTSTR lenin = len_trim ( instr ( 1 : len ( instr ) )) ! length of INSTR trimmed of trailing spaces lenout = len ( outstr ) ! number of characters output string OUTSTR can hold outstr = \" \" ! this SHOULD blank-fill string, a buggy machine required a loop to set all characters SCAN_LINE : do istep = 1 , lenin ! look through input string one character at a time c = instr ( istep : istep ) ! get next character iade = ichar ( c ) ! get ADE of the character EXPAND_TABS : select case ( iade ) ! take different actions depending on which character was found case ( 9 ) ! test if character is a tab and move pointer out to appropriate column ipos = ipos + ( tabsize - ( mod ( ipos - 1 , tabsize ))) case ( 10 , 13 ) ! convert carriage-return and new-line to space ,typically to handle DOS-format files ipos = ipos + 1 case default ! c is anything else other than a tab,newline,or return insert it in output string if ( ipos > lenout ) then write ( stderr , * ) \"*notabs* output string overflow\" exit else outstr ( ipos : ipos ) = c ipos = ipos + 1 endif end select EXPAND_TABS enddo SCAN_LINE ipos = min ( ipos , lenout ) ! tabs or newline or return characters or last character might have gone too far ilen = len_trim ( outstr (: ipos )) ! trim trailing spaces end subroutine notabs !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!##NAME !! dilate(3f) - [M_strings:NONALPHA] expand tab characters !! (LICENSE:PD) !! !!##SYNOPSIS !! !! function dilate(INSTR) result(OUTSTR) !! !! character(len=*),intent=(in) :: INSTR !! character(len=:),allocatable :: OUTSTR !! !!##DESCRIPTION !! dilate() converts tabs in INSTR to spaces in OUTSTR. It assumes a !! tab is set every 8 characters. Trailing spaces are removed. !! !! In addition, trailing carriage returns and line feeds are removed !! (they are usually a problem created by going to and from MSWindows). !! !!##OPTIONS !! instr Input line to remove tabs from !! !!##RESULTS !! outstr Output string with tabs expanded. !! !!##EXAMPLES !! !! Sample program: !! !! program demo_dilate !! !! use M_strings, only : dilate !! implicit none !! character(len=:),allocatable :: in !! integer :: i !! in=' this is my string ' !! ! change spaces to tabs to make a sample input !! do i=1,len(in) !! if(in(i:i) == ' ')in(i:i)=char(9) !! enddo !! write(*,'(a)')in,dilate(in) !! end program demo_dilate !! function dilate ( instr ) result ( outstr ) character ( len =* ), intent ( in ) :: instr ! input line to scan for tab characters character ( len = :), allocatable :: outstr ! tab-expanded version of INSTR produced integer :: i integer :: icount integer :: lgth icount = 0 do i = 1 , len ( instr ) if ( instr ( i : i ) == char ( 9 )) icount = icount + 1 end do allocate ( character ( len = ( len ( instr ) + 8 * icount )) :: outstr ) call notabs ( instr , outstr , lgth ) outstr = outstr (: lgth ) end function dilate end module fpm_strings","tags":"","loc":"sourcefile/fpm_strings.f90.html"},{"title":"fpm_pkg_config.f90 – Fortran-lang/fpm","text":"Source Code !># The fpm interface to pkg-config !> !> This module contains wrapper functions to interface with a pkg-config installation. !> module fpm_pkg_config use fpm_strings , only : string_t , str_begins_with_str , len_trim , remove_newline_characters , & split use fpm_error , only : error_t , fatal_error , fpm_stop use fpm_filesystem , only : get_temp_filename , getline use fpm_environment , only : get_env , os_is_unix , set_env , delete_env use shlex_module , only : shlex_split => split implicit none private public :: assert_pkg_config public :: pkgcfg_get_version public :: pkgcfg_get_libs public :: pkgcfg_get_build_flags public :: pkgcfg_has_package public :: pkgcfg_list_all public :: run_wrapper contains !> Check whether pkg-config is available on the local system logical function assert_pkg_config () integer :: exitcode logical :: success type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), args = [ string_t ( '-h' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) assert_pkg_config = exitcode == 0 . and . success end function assert_pkg_config !> Get package version from pkg-config type ( string_t ) function pkgcfg_get_version ( package , error ) result ( screen ) !> Package name character ( * ), intent ( in ) :: package !> Error handler type ( error_t ), allocatable , intent ( out ) :: error integer :: exitcode logical :: success type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( package ), string_t ( '--modversion' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) screen = log else screen = string_t ( \"\" ) end if end function pkgcfg_get_version !> Check if pkgcfg has package logical function pkgcfg_has_package ( name ) result ( success ) !> Package name character ( * ), intent ( in ) :: name integer :: exitcode logical :: cmdok type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( name ), string_t ( '--exists' )], & exitcode = exitcode , cmd_success = cmdok , screen_output = log ) !> pkg-config --exists returns 0 only if the package exists success = cmdok . and . exitcode == 0 end function pkgcfg_has_package !> Get package libraries from pkg-config function pkgcfg_get_libs ( package , error ) result ( libraries ) !> Package name character ( * ), intent ( in ) :: package !> Error handler type ( error_t ), allocatable , intent ( out ) :: error !> A list of libraries type ( string_t ), allocatable :: libraries (:) integer :: exitcode , nlib , i logical :: success character ( len = :), allocatable :: tokens (:) type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( package ), string_t ( '--libs' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) ! Split all arguments tokens = shlex_split ( log % s ) nlib = size ( tokens ) allocate ( libraries ( nlib )) do i = 1 , nlib libraries ( i ) = string_t ( trim ( adjustl ( tokens ( i )))) end do else allocate ( libraries ( 0 )) call fatal_error ( error , 'cannot get <' // package // '> libraries from pkg-config' ) end if end function pkgcfg_get_libs !> Return whole list of available pkg-cfg packages function pkgcfg_list_all ( error , descriptions ) result ( modules ) !> Error handler type ( error_t ), allocatable , intent ( out ) :: error !> A list of all available packages type ( string_t ), allocatable :: modules (:) !> An optional list of package descriptions type ( string_t ), optional , allocatable , intent ( out ) :: descriptions (:) integer :: exitcode , i , spc logical :: success character ( len = :), allocatable :: lines (:) type ( string_t ) :: log type ( string_t ), allocatable :: mods (:), descr (:) character ( * ), parameter :: CRLF = achar ( 13 ) // new_line ( 'a' ) call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( '--list-all' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if (. not .( success . and . exitcode == 0 )) then call fatal_error ( error , 'cannot get pkg-config modules' ) allocate ( modules ( 0 )) return end if !> Extract list call split ( log % s , lines , CRLF ) allocate ( mods ( size ( lines )), descr ( size ( lines ))) do i = 1 , size ( lines ) ! Module names have no spaces spc = index ( lines ( i ), ' ' ) if ( spc > 0 ) then mods ( i ) = string_t ( trim ( adjustl ( lines ( i )( 1 : spc )))) descr ( i ) = string_t ( trim ( adjustl ( lines ( i )( spc + 1 :)))) else mods ( i ) = string_t ( trim ( adjustl ( lines ( i )))) descr ( i ) = string_t ( \"\" ) end if end do call move_alloc ( from = mods , to = modules ) if ( present ( descriptions )) call move_alloc ( from = descr , to = descriptions ) end function pkgcfg_list_all !> Get build flags (option to include flags from system directories, that !> gfortran does not look into by default) function pkgcfg_get_build_flags ( name , allow_system , error ) result ( flags ) !> Package name character ( * ), intent ( in ) :: name !> Should pkg-config look in system paths? This is necessary for gfortran !> that doesn't otherwise look into them logical , intent ( in ) :: allow_system !> Error flag type ( error_t ), allocatable , intent ( out ) :: error !> List of compile flags type ( string_t ), allocatable :: flags (:) integer :: exitcode , i , nlib logical :: old_had , success , old_allow character (:), allocatable :: old , tokens (:) type ( string_t ) :: log ! Check if the current environment includes system flags old = get_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , default = 'ERROR' ) old_had = old /= 'ERROR' old_allow = merge ( old == '1' ,. false ., old_had ) ! Set system flags success = set_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , value = merge ( '1' , '0' , allow_system )) if (. not . success ) then call fatal_error ( error , 'Cannot get pkg-config build flags: environment variable error.' ) return end if ! Now run wrapper call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( name ), string_t ( '--cflags' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) ! Split all arguments tokens = shlex_split ( log % s ) nlib = size ( tokens ) allocate ( flags ( nlib )) do i = 1 , nlib flags ( i ) = string_t ( trim ( adjustl ( tokens ( i )))) end do else allocate ( flags ( 0 )) call fatal_error ( error , 'cannot get <' // name // '> build flags from pkg-config' ) end if ! Restore environment variable if ( old_had ) then success = set_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , value = old ) else success = delete_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' ) end if if (. not . success ) then call fatal_error ( error , 'Cannot get pkg-config build flags: environment variable error.' ) return end if end function pkgcfg_get_build_flags !> Simple call to execute_command_line involving one mpi* wrapper subroutine run_wrapper ( wrapper , args , verbose , exitcode , cmd_success , screen_output ) type ( string_t ), intent ( in ) :: wrapper type ( string_t ), intent ( in ), optional :: args (:) logical , intent ( in ), optional :: verbose integer , intent ( out ), optional :: exitcode logical , intent ( out ), optional :: cmd_success type ( string_t ), intent ( out ), optional :: screen_output logical :: echo_local character (:), allocatable :: redirect_str , command , redirect , line integer :: iunit , iarg , stat , cmdstat if ( present ( verbose )) then echo_local = verbose else echo_local = . false . end if ! No redirection and non-verbose output if ( present ( screen_output )) then redirect = get_temp_filename () redirect_str = \">\" // redirect // \" 2>&1\" else if ( os_is_unix ()) then redirect_str = \" >/dev/null 2>&1\" else redirect_str = \" >NUL 2>&1\" end if end if ! Empty command if ( len_trim ( wrapper ) <= 0 ) then if ( echo_local ) print * , '+ ' if ( present ( exitcode )) exitcode = 0 if ( present ( cmd_success )) cmd_success = . true . if ( present ( screen_output )) screen_output = string_t ( \"\" ) return end if ! Init command command = trim ( wrapper % s ) add_arguments : if ( present ( args )) then do iarg = 1 , size ( args ) if ( len_trim ( args ( iarg )) <= 0 ) cycle command = trim ( command ) // ' ' // args ( iarg )% s end do endif add_arguments if ( echo_local ) print * , '+ ' , command ! Test command call execute_command_line ( command // redirect_str , exitstat = stat , cmdstat = cmdstat ) ! Command successful? if ( present ( cmd_success )) cmd_success = cmdstat == 0 ! Program exit code? if ( present ( exitcode )) exitcode = stat ! Want screen output? if ( present ( screen_output ) . and . cmdstat == 0 ) then allocate ( character ( len = 0 ) :: screen_output % s ) open ( newunit = iunit , file = redirect , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit screen_output % s = screen_output % s // new_line ( 'a' ) // line if ( echo_local ) write ( * , '(A)' ) trim ( line ) end do ! Close and delete file close ( iunit , status = 'delete' ) else call fpm_stop ( 1 , 'cannot read temporary file from successful MPI wrapper' ) endif end if end subroutine run_wrapper end module fpm_pkg_config","tags":"","loc":"sourcefile/fpm_pkg_config.f90.html"},{"title":"main.f90 – Fortran-lang/fpm","text":"Source Code program main use , intrinsic :: iso_fortran_env , only : error_unit , output_unit use fpm_command_line , only : & fpm_cmd_settings , & fpm_new_settings , & fpm_build_settings , & fpm_export_settings , & fpm_run_settings , & fpm_test_settings , & fpm_install_settings , & fpm_update_settings , & fpm_clean_settings , & fpm_publish_settings , & get_command_line_settings use fpm_error , only : error_t use fpm_filesystem , only : exists , parent_dir , join_path use fpm , only : cmd_build , cmd_run , cmd_clean use fpm_cmd_install , only : cmd_install use fpm_cmd_export , only : cmd_export use fpm_cmd_new , only : cmd_new use fpm_cmd_update , only : cmd_update use fpm_cmd_publish , only : cmd_publish use fpm_os , only : change_directory , get_current_directory implicit none class ( fpm_cmd_settings ), allocatable :: cmd_settings type ( error_t ), allocatable :: error character ( len = :), allocatable :: pwd_start , pwd_working , working_dir , project_root call get_command_line_settings ( cmd_settings ) call get_current_directory ( pwd_start , error ) call handle_error ( error ) call get_working_dir ( cmd_settings , working_dir ) if ( allocated ( working_dir )) then ! Change working directory if requested if ( len_trim ( working_dir ) > 0 ) then call change_directory ( working_dir , error ) call handle_error ( error ) call get_current_directory ( pwd_working , error ) call handle_error ( error ) write ( output_unit , '(*(a))' ) \"fpm: Entering directory '\" // pwd_working // \"'\" else pwd_working = pwd_start end if else pwd_working = pwd_start end if select type ( settings => cmd_settings ) type is ( fpm_new_settings ) class default if (. not . has_manifest ( pwd_working )) then project_root = pwd_working do while (. not . has_manifest ( project_root )) working_dir = parent_dir ( project_root ) if ( len ( working_dir ) == 0 ) exit project_root = working_dir end do if ( has_manifest ( project_root )) then call change_directory ( project_root , error ) call handle_error ( error ) write ( output_unit , '(*(a))' ) \"fpm: Entering directory '\" // project_root // \"'\" end if end if end select select type ( settings => cmd_settings ) type is ( fpm_new_settings ) call cmd_new ( settings ) type is ( fpm_build_settings ) call cmd_build ( settings ) type is ( fpm_run_settings ) call cmd_run ( settings , test = . false .) type is ( fpm_test_settings ) call cmd_run ( settings , test = . true .) type is ( fpm_export_settings ) call cmd_export ( settings ) type is ( fpm_install_settings ) call cmd_install ( settings ) type is ( fpm_update_settings ) call cmd_update ( settings ) type is ( fpm_clean_settings ) call cmd_clean ( settings ) type is ( fpm_publish_settings ) call cmd_publish ( settings ) end select if ( allocated ( project_root )) then write ( output_unit , '(*(a))' ) \"fpm: Leaving directory '\" // project_root // \"'\" end if if ( pwd_start /= pwd_working ) then write ( output_unit , '(*(a))' ) \"fpm: Leaving directory '\" // pwd_working // \"'\" end if contains function has_manifest ( dir ) character ( len =* ), intent ( in ) :: dir logical :: has_manifest has_manifest = exists ( join_path ( dir , \"fpm.toml\" )) end function has_manifest subroutine handle_error ( error_ ) type ( error_t ), optional , intent ( in ) :: error_ if ( present ( error_ )) then write ( error_unit , '(\"[Error]\", 1x, a)' ) error_ % message stop 1 end if end subroutine handle_error !> Save access to working directory in settings, in case setting have not been allocated subroutine get_working_dir ( settings , working_dir_ ) class ( fpm_cmd_settings ), optional , intent ( in ) :: settings character ( len = :), allocatable , intent ( out ) :: working_dir_ if ( present ( settings )) then working_dir_ = settings % working_dir end if end subroutine get_working_dir end program main","tags":"","loc":"sourcefile/main.f90.html"},{"title":"fpm_meta.f90 – Fortran-lang/fpm","text":"Source Code !># The fpm meta-package model !> !> This is a wrapper data type that encapsulate all pre-processing information !> (compiler flags, linker libraries, etc.) required to correctly enable a package !> to use a core library. !> !> !>### Available core libraries !> !> - OpenMP !> - MPI !> - HDF5 !> - fortran-lang stdlib !> - fortran-lang minpack !> !> !> @note Core libraries are enabled in the [build] section of the fpm.toml manifest !> !> module fpm_meta use fpm_strings , only : string_t , len_trim , remove_newline_characters , str_begins_with_str , & str_ends_with use fpm_error , only : error_t , fatal_error , syntax_error , fpm_stop use fpm_compiler use fpm_model use fpm_command_line use fpm_manifest_dependency , only : dependency_config_t use fpm_git , only : git_target_branch , git_target_tag use fpm_manifest , only : package_config_t use fpm_environment , only : get_env , os_is_unix , set_env , delete_env use fpm_filesystem , only : run , get_temp_filename , getline , exists , canon_path , is_dir , get_dos_path use fpm_versioning , only : version_t , new_version , regex_version_from_text use fpm_os , only : get_absolute_path use fpm_pkg_config use shlex_module , only : shlex_split => split use regex_module , only : regex use iso_fortran_env , only : stdout => output_unit implicit none private public :: resolve_metapackages !> Type for describing a source file type , public :: metapackage_t !> Package version (if supported) type ( version_t ), allocatable :: version logical :: has_link_libraries = . false . logical :: has_link_flags = . false . logical :: has_build_flags = . false . logical :: has_fortran_flags = . false . logical :: has_c_flags = . false . logical :: has_cxx_flags = . false . logical :: has_include_dirs = . false . logical :: has_dependencies = . false . logical :: has_run_command = . false . logical :: has_external_modules = . false . !> List of compiler flags and options to be added type ( string_t ) :: flags type ( string_t ) :: fflags type ( string_t ) :: cflags type ( string_t ) :: cxxflags type ( string_t ) :: link_flags type ( string_t ) :: run_command type ( string_t ), allocatable :: incl_dirs (:) type ( string_t ), allocatable :: link_libs (:) type ( string_t ), allocatable :: external_modules (:) !> Special fortran features type ( fortran_features_t ), allocatable :: fortran !> List of Development dependency meta data. !> Metapackage dependencies are never exported from the model type ( dependency_config_t ), allocatable :: dependency (:) contains !> Clean metapackage structure procedure :: destroy !> Initialize the metapackage structure from its given name procedure :: new => init_from_name !> Add metapackage dependencies to the model procedure , private :: resolve_cmd procedure , private :: resolve_model procedure , private :: resolve_package_config generic :: resolve => resolve_cmd , resolve_model , resolve_package_config end type metapackage_t interface resolve_metapackages module procedure resolve_metapackage_model end interface resolve_metapackages integer , parameter :: MPI_TYPE_NONE = 0 integer , parameter :: MPI_TYPE_OPENMPI = 1 integer , parameter :: MPI_TYPE_MPICH = 2 integer , parameter :: MPI_TYPE_INTEL = 3 integer , parameter :: MPI_TYPE_MSMPI = 4 public :: MPI_TYPE_NAME !> Debugging information logical , parameter , private :: verbose = . false . integer , parameter , private :: LANG_FORTRAN = 1 integer , parameter , private :: LANG_C = 2 integer , parameter , private :: LANG_CXX = 3 character ( * ), parameter :: LANG_NAME ( * ) = [ character ( 7 ) :: 'Fortran' , 'C' , 'C++' ] contains !> Return a name for the MPI library pure function MPI_TYPE_NAME ( mpilib ) result ( name ) integer , intent ( in ) :: mpilib character ( len = :), allocatable :: name select case ( mpilib ) case ( MPI_TYPE_NONE ); name = \"none\" case ( MPI_TYPE_OPENMPI ); name = \"OpenMPI\" case ( MPI_TYPE_MPICH ); name = \"MPICH\" case ( MPI_TYPE_INTEL ); name = \"INTELMPI\" case ( MPI_TYPE_MSMPI ); name = \"MS-MPI\" case default ; name = \"UNKNOWN\" end select end function MPI_TYPE_NAME !> Clean the metapackage structure elemental subroutine destroy ( this ) class ( metapackage_t ), intent ( inout ) :: this this % has_link_libraries = . false . this % has_link_flags = . false . this % has_build_flags = . false . this % has_fortran_flags = . false . this % has_c_flags = . false . this % has_cxx_flags = . false . this % has_include_dirs = . false . this % has_dependencies = . false . this % has_run_command = . false . this % has_external_modules = . false . if ( allocated ( this % fortran )) deallocate ( this % fortran ) if ( allocated ( this % version )) deallocate ( this % version ) if ( allocated ( this % flags % s )) deallocate ( this % flags % s ) if ( allocated ( this % fflags % s )) deallocate ( this % fflags % s ) if ( allocated ( this % cflags % s )) deallocate ( this % cflags % s ) if ( allocated ( this % cxxflags % s )) deallocate ( this % cxxflags % s ) if ( allocated ( this % link_flags % s )) deallocate ( this % link_flags % s ) if ( allocated ( this % run_command % s )) deallocate ( this % run_command % s ) if ( allocated ( this % link_libs )) deallocate ( this % link_libs ) if ( allocated ( this % dependency )) deallocate ( this % dependency ) if ( allocated ( this % incl_dirs )) deallocate ( this % incl_dirs ) if ( allocated ( this % external_modules )) deallocate ( this % external_modules ) end subroutine destroy !> Initialize a metapackage from the given name subroutine init_from_name ( this , name , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this character ( * ), intent ( in ) :: name type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error !> Initialize metapackage by name select case ( name ) case ( \"openmp\" ); call init_openmp ( this , compiler , error ) case ( \"stdlib\" ); call init_stdlib ( this , compiler , error ) case ( \"minpack\" ); call init_minpack ( this , compiler , error ) case ( \"mpi\" ); call init_mpi ( this , compiler , error ) case ( \"hdf5\" ); call init_hdf5 ( this , compiler , error ) case default call syntax_error ( error , \"Package \" // name // \" is not supported in [metapackages]\" ) return end select end subroutine init_from_name !> Initialize OpenMP metapackage for the current system subroutine init_openmp ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error !> Cleanup call destroy ( this ) !> OpenMP has compiler flags this % has_build_flags = . true . this % has_link_flags = . true . !> OpenMP flags should be added to which_compiler : select case ( compiler % id ) case ( id_gcc , id_f95 ) this % flags = string_t ( flag_gnu_openmp ) this % link_flags = string_t ( flag_gnu_openmp ) case ( id_intel_classic_windows , id_intel_llvm_windows ) this % flags = string_t ( flag_intel_openmp_win ) this % link_flags = string_t ( flag_intel_openmp_win ) case ( id_intel_classic_nix , id_intel_classic_mac ,& id_intel_llvm_nix ) this % flags = string_t ( flag_intel_openmp ) this % link_flags = string_t ( flag_intel_openmp ) case ( id_pgi , id_nvhpc ) this % flags = string_t ( flag_pgi_openmp ) this % link_flags = string_t ( flag_pgi_openmp ) case ( id_ibmxl ) this % flags = string_t ( \" -qsmp=omp\" ) this % link_flags = string_t ( \" -qsmp=omp\" ) case ( id_nag ) this % flags = string_t ( flag_nag_openmp ) this % link_flags = string_t ( flag_nag_openmp ) case ( id_lfortran ) this % flags = string_t ( flag_lfortran_openmp ) this % link_flags = string_t ( flag_lfortran_openmp ) case default call fatal_error ( error , 'openmp not supported on compiler ' // compiler % name () // ' yet' ) end select which_compiler end subroutine init_openmp !> Initialize minpack metapackage for the current system subroutine init_minpack ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error !> Cleanup call destroy ( this ) !> minpack is queried as a dependency from the official repository this % has_dependencies = . true . allocate ( this % dependency ( 1 )) !> 1) minpack. There are no true releases currently. Fetch HEAD this % dependency ( 1 )% name = \"minpack\" this % dependency ( 1 )% git = git_target_tag ( \"https://github.com/fortran-lang/minpack\" , \"v2.0.0-rc.1\" ) if (. not . allocated ( this % dependency ( 1 )% git )) then call fatal_error ( error , 'cannot initialize git repo dependency for minpack metapackage' ) return end if end subroutine init_minpack !> Initialize stdlib metapackage for the current system subroutine init_stdlib ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error !> Cleanup call destroy ( this ) !> Stdlib is queried as a dependency from the official repository this % has_dependencies = . true . allocate ( this % dependency ( 2 )) !> 1) Test-drive this % dependency ( 1 )% name = \"test-drive\" this % dependency ( 1 )% git = git_target_branch ( \"https://github.com/fortran-lang/test-drive\" , \"v0.4.0\" ) if (. not . allocated ( this % dependency ( 1 )% git )) then call fatal_error ( error , 'cannot initialize test-drive git dependency for stdlib metapackage' ) return end if !> 2) stdlib this % dependency ( 2 )% name = \"stdlib\" this % dependency ( 2 )% git = git_target_branch ( \"https://github.com/fortran-lang/stdlib\" , \"stdlib-fpm\" ) if (. not . allocated ( this % dependency ( 2 )% git )) then call fatal_error ( error , 'cannot initialize git repo dependency for stdlib metapackage' ) return end if end subroutine init_stdlib ! Resolve metapackage dependencies into the command line settings subroutine resolve_cmd ( self , settings , error ) class ( metapackage_t ), intent ( in ) :: self class ( fpm_cmd_settings ), intent ( inout ) :: settings type ( error_t ), allocatable , intent ( out ) :: error ! Add customize run commands if ( self % has_run_command ) then select type ( cmd => settings ) class is ( fpm_run_settings ) ! includes fpm_test_settings ! Only override runner if user has not provided a custom one if (. not . len_trim ( cmd % runner ) > 0 ) cmd % runner = self % run_command % s end select endif end subroutine resolve_cmd ! Resolve metapackage dependencies into the model subroutine resolve_model ( self , model , error ) class ( metapackage_t ), intent ( in ) :: self type ( fpm_model_t ), intent ( inout ) :: model type ( error_t ), allocatable , intent ( out ) :: error ! Add global build flags, to apply to all sources if ( self % has_build_flags ) then model % fortran_compile_flags = model % fortran_compile_flags // self % flags % s model % c_compile_flags = model % c_compile_flags // self % flags % s model % cxx_compile_flags = model % cxx_compile_flags // self % flags % s endif ! Add language-specific flags if ( self % has_fortran_flags ) model % fortran_compile_flags = model % fortran_compile_flags // self % fflags % s if ( self % has_c_flags ) model % c_compile_flags = model % c_compile_flags // self % cflags % s if ( self % has_cxx_flags ) model % cxx_compile_flags = model % cxx_compile_flags // self % cxxflags % s if ( self % has_link_flags ) then model % link_flags = model % link_flags // ' ' // self % link_flags % s end if if ( self % has_link_libraries ) then model % link_libraries = [ model % link_libraries , self % link_libs ] end if if ( self % has_include_dirs ) then model % include_dirs = [ model % include_dirs , self % incl_dirs ] end if if ( self % has_external_modules ) then model % external_modules = [ model % external_modules , self % external_modules ] end if end subroutine resolve_model subroutine resolve_package_config ( self , package , error ) class ( metapackage_t ), intent ( in ) :: self type ( package_config_t ), intent ( inout ) :: package type ( error_t ), allocatable , intent ( out ) :: error ! All metapackage dependencies are added as dev-dependencies, ! as they may change if built upstream if ( self % has_dependencies ) then if ( allocated ( package % dev_dependency )) then package % dev_dependency = [ package % dev_dependency , self % dependency ] else package % dev_dependency = self % dependency end if end if ! Check if there are any special fortran requests which the package does not comply to if ( allocated ( self % fortran )) then if ( self % fortran % implicit_external . neqv . package % fortran % implicit_external ) then call fatal_error ( error , 'metapackage fortran error: metapackage ' // & dn ( self % fortran % implicit_external ) // ' require implicit-external, main package ' // & dn ( package % fortran % implicit_external )) return end if if ( self % fortran % implicit_typing . neqv . package % fortran % implicit_typing ) then call fatal_error ( error , 'metapackage fortran error: metapackage ' // & dn ( self % fortran % implicit_external ) // ' require implicit-typing, main package ' // & dn ( package % fortran % implicit_external )) return end if end if contains pure function dn ( bool ) logical , intent ( in ) :: bool character ( len = :), allocatable :: dn if ( bool ) then dn = \"does\" else dn = \"does not\" end if end function dn end subroutine resolve_package_config ! Add named metapackage dependency to the model subroutine add_metapackage_model ( model , package , settings , name , error ) type ( fpm_model_t ), intent ( inout ) :: model type ( package_config_t ), intent ( inout ) :: package class ( fpm_cmd_settings ), intent ( inout ) :: settings character ( * ), intent ( in ) :: name type ( error_t ), allocatable , intent ( out ) :: error type ( metapackage_t ) :: meta !> Init metapackage call meta % new ( name , model % compiler , error ) if ( allocated ( error )) return !> Add it into the model call meta % resolve ( model , error ) if ( allocated ( error )) return !> Add it into the package call meta % resolve ( package , error ) if ( allocated ( error )) return !> Add it into the settings call meta % resolve ( settings , error ) if ( allocated ( error )) return ! If we need to run executables, there should be an MPI runner if ( name == \"mpi\" ) then select type ( settings ) class is ( fpm_run_settings ) ! run, test if (. not . meta % has_run_command ) & call fatal_error ( error , \"cannot find a valid mpi runner on the local host\" ) end select endif end subroutine add_metapackage_model !> Resolve all metapackages into the package config subroutine resolve_metapackage_model ( model , package , settings , error ) type ( fpm_model_t ), intent ( inout ) :: model type ( package_config_t ), intent ( inout ) :: package class ( fpm_build_settings ), intent ( inout ) :: settings type ( error_t ), allocatable , intent ( out ) :: error ! Dependencies are added to the package config, so they're properly resolved ! into the dependency tree later. ! Flags are added to the model (whose compiler needs to be already initialized) if ( model % compiler % is_unknown ()) & write ( stdout , '(a)' ) ' compiler not initialized: metapackages may not be available' ! OpenMP if ( package % meta % openmp % on ) then call add_metapackage_model ( model , package , settings , \"openmp\" , error ) if ( allocated ( error )) return endif ! stdlib if ( package % meta % stdlib % on ) then call add_metapackage_model ( model , package , settings , \"stdlib\" , error ) if ( allocated ( error )) return endif ! minpack if ( package % meta % minpack % on ) then call add_metapackage_model ( model , package , settings , \"minpack\" , error ) if ( allocated ( error )) return endif ! Stdlib is not 100% thread safe. print a warning to the user if ( package % meta % stdlib % on . and . package % meta % openmp % on ) then write ( stdout , '(a)' ) ' both openmp and stdlib requested: some functions may not be thread-safe!' end if ! MPI if ( package % meta % mpi % on ) then call add_metapackage_model ( model , package , settings , \"mpi\" , error ) if ( allocated ( error )) return endif ! hdf5 if ( package % meta % hdf5 % on ) then call add_metapackage_model ( model , package , settings , \"hdf5\" , error ) if ( allocated ( error )) return endif end subroutine resolve_metapackage_model !> Initialize MPI metapackage for the current system subroutine init_mpi ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error type ( string_t ), allocatable :: c_wrappers (:), cpp_wrappers (:), fort_wrappers (:) type ( string_t ) :: output , fwrap , cwrap , cxxwrap character ( 256 ) :: msg_out character ( len = :), allocatable :: tokens (:) integer :: wcfit ( 3 ), mpilib ( 3 ), ic , icpp , i logical :: found !> Cleanup call destroy ( this ) !> Get all candidate MPI wrappers call mpi_wrappers ( compiler , fort_wrappers , c_wrappers , cpp_wrappers ) if ( verbose ) print 1 , size ( fort_wrappers ), size ( c_wrappers ), size ( cpp_wrappers ) call wrapper_compiler_fit ( fort_wrappers , c_wrappers , cpp_wrappers , compiler , wcfit , mpilib , error ) if ( allocated ( error ) . or . all ( wcfit == 0 )) then !> No wrapper compiler fit. Are we on Windows? use MSMPI-specific search found = msmpi_init ( this , compiler , error ) if ( allocated ( error )) return !> All attempts failed if (. not . found ) then call fatal_error ( error , \"cannot find MPI wrappers or libraries for \" // compiler % name () // \" compiler\" ) return endif else if ( wcfit ( LANG_FORTRAN ) > 0 ) fwrap = fort_wrappers ( wcfit ( LANG_FORTRAN )) if ( wcfit ( LANG_C ) > 0 ) cwrap = c_wrappers ( wcfit ( LANG_C )) if ( wcfit ( LANG_CXX ) > 0 ) cxxwrap = cpp_wrappers ( wcfit ( LANG_CXX )) !> If there's only an available Fortran wrapper, and the compiler's different than fpm's baseline !> fortran compiler suite, we still want to enable C language flags as that is most likely being !> ABI-compatible anyways. However, issues may arise. !> see e.g. Homebrew with clabng C/C++ and GNU fortran at https://gitlab.kitware.com/cmake/cmake/-/issues/18139 if ( wcfit ( LANG_FORTRAN ) > 0 . and . all ( wcfit ([ LANG_C , LANG_CXX ]) == 0 )) then cwrap = fort_wrappers ( wcfit ( LANG_FORTRAN )) cxxwrap = fort_wrappers ( wcfit ( LANG_FORTRAN )) end if if ( verbose ) print * , '+ MPI fortran wrapper: ' , fwrap % s if ( verbose ) print * , '+ MPI c wrapper: ' , cwrap % s if ( verbose ) print * , '+ MPI c++ wrapper: ' , cxxwrap % s !> Initialize MPI package from wrapper command call init_mpi_from_wrappers ( this , compiler , mpilib ( LANG_FORTRAN ), fwrap , cwrap , cxxwrap , error ) if ( allocated ( error )) return !> Request Fortran implicit typing if ( mpilib ( LANG_FORTRAN ) /= MPI_TYPE_INTEL ) then allocate ( this % fortran ) this % fortran % implicit_typing = . true . this % fortran % implicit_external = . true . endif end if !> Not all MPI implementations offer modules mpi and mpi_f08: hence, include them !> to the list of external modules, so they won't be requested as standard source files this % has_external_modules = . true . this % external_modules = [ string_t ( \"mpi\" ), string_t ( \"mpi_f08\" )] 1 format ( 'MPI wrappers found: fortran=' , i0 , ' c=' , i0 , ' c++=' , i0 ) end subroutine init_mpi !> Check if we're on a 64-bit environment !> Accept answer from https://stackoverflow.com/questions/49141093/get-system-information-with-fortran logical function is_64bit_environment () use iso_c_binding , only : c_intptr_t integer , parameter :: nbits = bit_size ( 0_c_intptr_t ) is_64bit_environment = nbits == 64 end function is_64bit_environment !> Check if there is a wrapper-compiler fit subroutine wrapper_compiler_fit ( fort_wrappers , c_wrappers , cpp_wrappers , compiler , wrap , mpi , error ) type ( string_t ), allocatable , intent ( in ) :: fort_wrappers (:), c_wrappers (:), cpp_wrappers (:) type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error integer , intent ( out ), dimension ( 3 ) :: wrap , mpi type ( error_t ), allocatable :: wrap_error wrap = 0 mpi = MPI_TYPE_NONE if ( size ( fort_wrappers ) > 0 ) & call mpi_compiler_match ( LANG_FORTRAN , fort_wrappers , compiler , wrap ( LANG_FORTRAN ), mpi ( LANG_FORTRAN ), wrap_error ) if ( size ( c_wrappers ) > 0 ) & call mpi_compiler_match ( LANG_C , c_wrappers , compiler , wrap ( LANG_C ), mpi ( LANG_C ), wrap_error ) if ( size ( cpp_wrappers ) > 0 ) & call mpi_compiler_match ( LANG_CXX , cpp_wrappers , compiler , wrap ( LANG_CXX ), mpi ( LANG_CXX ), wrap_error ) !> Find a Fortran wrapper for the current compiler if ( all ( wrap == 0 )) then call fatal_error ( error , 'no valid wrappers match current compiler, ' // compiler_name ( compiler )) return end if end subroutine wrapper_compiler_fit !> Check if a local MS-MPI SDK build is found logical function msmpi_init ( this , compiler , error ) result ( found ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: incdir , windir , libdir , bindir , post , reall , msysdir type ( version_t ) :: ver , ver10 type ( string_t ) :: cpath , msys_path , runner_path logical :: msys2 !> Default: not found found = . false . if ( get_os_type () == OS_WINDOWS ) then ! to run MSMPI on Windows, is_minGW : if ( compiler % id == id_gcc ) then call compiler_get_version ( compiler , ver , msys2 , error ) if ( allocated ( error )) return endif is_minGW ! Check we're on a 64-bit environment if ( is_64bit_environment ()) then libdir = get_env ( 'MSMPI_LIB64' ) post = 'x64' else libdir = get_env ( 'MSMPI_LIB32' ) post = 'x86' !> Not working on 32-bit Windows yet call fatal_error ( error , 'MS-MPI error: this package requires 64-bit Windows environment' ) return end if ! Check that the runtime is installed bindir = \"\" call get_absolute_path ( get_env ( 'MSMPI_BIN' ), bindir , error ) if ( verbose ) print * , '+ %MSMPI_BIN%=' , bindir ! In some environments, variable %MSMPI_BIN% is missing (i.e. in GitHub Action images). ! Do a second attempt: search for the default location if ( len_trim ( bindir ) <= 0 . or . allocated ( error )) then if ( verbose ) print * , '+ %MSMPI_BIN% empty, searching C:\\Program Files\\Microsoft MPI\\Bin\\ ...' call get_absolute_path ( 'C:\\Program Files\\Microsoft MPI\\Bin\\mpiexec.exe' , bindir , error ) endif ! Third attempt for bash-style shell if ( len_trim ( bindir ) <= 0 . or . allocated ( error )) then if ( verbose ) print * , '+ %MSMPI_BIN% empty, searching /c/Program Files/Microsoft MPI/Bin/ ...' call get_absolute_path ( '/c/Program Files/Microsoft MPI/Bin/mpiexec.exe' , bindir , error ) endif ! Do a fourth attempt: search for mpiexec.exe in PATH location if ( len_trim ( bindir ) <= 0 . or . allocated ( error )) then if ( verbose ) print * , '+ C:\\Program Files\\Microsoft MPI\\Bin\\ not found. searching %PATH%...' call get_mpi_runner ( runner_path , verbose , error ) if (. not . allocated ( error )) then if ( verbose ) print * , '+ mpiexec found: ' , runner_path % s call find_command_location ( runner_path % s , bindir , verbose = verbose , error = error ) endif endif if ( allocated ( error )) then call fatal_error ( error , 'MS-MPI error: MS-MPI Runtime directory is missing. ' // & 'check environment variable %MSMPI_BIN% or that the folder is in %PATH%.' ) return end if ! Success! found = . true . ! Init ms-mpi call destroy ( this ) ! MSYS2 provides a pre-built static msmpi.dll.a library. Use that if possible use_prebuilt : if ( msys2 ) then ! MSYS executables are in %MSYS_ROOT%/bin call compiler_get_path ( compiler , cpath , error ) if ( allocated ( error )) return call get_absolute_path ( join_path ( cpath % s , '..' ), msys_path % s , error ) if ( allocated ( error )) return call get_absolute_path ( join_path ( msys_path % s , 'include' ), incdir , error ) if ( allocated ( error )) return call get_absolute_path ( join_path ( msys_path % s , 'lib' ), libdir , error ) if ( allocated ( error )) return if ( verbose ) print 1 , 'include' , incdir , exists ( incdir ) if ( verbose ) print 1 , 'library' , libdir , exists ( libdir ) ! Check that the necessary files exist call get_absolute_path ( join_path ( libdir , 'libmsmpi.dll.a' ), post , error ) if ( allocated ( error )) return if ( len_trim ( post ) <= 0 . or . . not . exists ( post )) then call fatal_error ( error , 'MS-MPI available through the MSYS2 system not found. ' // & 'Run ' // & 'or your system-specific version to install.' ) return end if ! Add dir cpath this % has_link_flags = . true . this % link_flags = string_t ( ' -L' // get_dos_path ( libdir , error )) this % has_link_libraries = . true . this % link_libs = [ string_t ( 'msmpi.dll' )] if ( allocated ( error )) return this % has_include_dirs = . true . this % incl_dirs = [ string_t ( get_dos_path ( incdir , error ))] if ( allocated ( error )) return else call fatal_error ( error , 'MS-MPI cannot work with non-MSYS2 GNU compilers yet' ) return ! Add dir path this % has_link_flags = . true . this % link_flags = string_t ( ' -L' // get_dos_path ( libdir , error )) this % has_link_libraries = . true . this % link_libs = [ string_t ( 'msmpi' ), string_t ( 'msmpifec' ), string_t ( 'msmpifmc' )] if ( allocated ( error )) return this % has_include_dirs = . true . this % incl_dirs = [ string_t ( get_dos_path ( incdir , error )), & string_t ( get_dos_path ( incdir // post , error ))] if ( allocated ( error )) return end if use_prebuilt !> Request Fortran implicit typing allocate ( this % fortran ) this % fortran % implicit_typing = . true . this % fortran % implicit_external = . true . ! gfortran>=10 is incompatible with the old-style mpif.h MS-MPI headers. ! If so, add flags to allow old-style BOZ constants in mpif.h allow_BOZ : if ( compiler % id == id_gcc ) then call new_version ( ver10 , '10.0.0' , error ) if ( allocated ( error )) return if ( ver >= ver10 ) then this % has_build_flags = . true . this % flags = string_t ( ' -fallow-invalid-boz' ) end if endif allow_BOZ !> Add default run command this % has_run_command = . true . this % run_command = string_t ( join_path ( get_dos_path ( bindir , error ), 'mpiexec.exe' ) // ' -np * ' ) else !> Not on Windows found = . false . end if 1 format ( 'MSMSPI ' , a , ' directory: PATH=' , a , ' EXISTS=' , l1 ) end function msmpi_init !> Check if we're under a WSL bash shell logical function wsl_shell () if ( get_os_type () == OS_WINDOWS ) then wsl_shell = exists ( '/proc/sys/fs/binfmt_misc/WSLInterop' ) else wsl_shell = . false . endif end function wsl_shell !> Find the location of a valid command subroutine find_command_location ( command , path , echo , verbose , error ) character ( * ), intent ( in ) :: command character ( len = :), allocatable , intent ( out ) :: path logical , optional , intent ( in ) :: echo , verbose type ( error_t ), allocatable , intent ( out ) :: error character (:), allocatable :: tmp_file , screen_output , line , fullpath , search_command integer :: stat , iunit , ire , length , try character ( * ), parameter :: search ( 2 ) = [ \"where \" , \"which \" ] if ( len_trim ( command ) <= 0 ) then call fatal_error ( error , 'empty command provided in find_command_location' ) return end if tmp_file = get_temp_filename () ! On Windows, we try both commands because we may be on WSL do try = merge ( 1 , 2 , get_os_type () == OS_WINDOWS ), 2 search_command = search ( try ) // command call run ( search_command , echo = echo , exitstat = stat , verbose = verbose , redirect = tmp_file ) if ( stat == 0 ) exit end do if ( stat /= 0 ) then call fatal_error ( error , 'find_command_location failed for ' // command ) return end if ! Only read first instance (first line) allocate ( character ( len = 0 ) :: screen_output ) open ( newunit = iunit , file = tmp_file , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit if ( len ( screen_output ) > 0 ) then screen_output = screen_output // new_line ( 'a' ) // line else screen_output = line endif end do ! Close and delete file close ( iunit , status = 'delete' ) else call fatal_error ( error , 'cannot read temporary file from successful find_command_location' ) return endif ! Only use the first instance length = index ( screen_output , new_line ( 'a' )) multiline : if ( length > 1 ) then fullpath = screen_output ( 1 : length - 1 ) else fullpath = screen_output endif multiline if ( len_trim ( fullpath ) < 1 ) then call fatal_error ( error , 'no paths found to command (' // command // ')' ) return end if ! Extract path only length = index ( fullpath , command , BACK = . true .) if ( length <= 0 ) then call fatal_error ( error , 'full path to command (' // command // ') does not include command name' ) return elseif ( length == 1 ) then ! Compiler is in the current folder path = '.' else path = fullpath ( 1 : length - 1 ) end if if ( allocated ( error )) return ! On Windows, be sure to return a path with no spaces if ( get_os_type () == OS_WINDOWS ) path = get_dos_path ( path , error ) if ( allocated ( error ) . or . . not . is_dir ( path )) then call fatal_error ( error , 'full path (' // path // ') to command (' // command // ') is not a directory' ) return end if end subroutine find_command_location !> Get MPI runner in $PATH subroutine get_mpi_runner ( command , verbose , error ) type ( string_t ), intent ( out ) :: command logical , intent ( in ) :: verbose type ( error_t ), allocatable , intent ( out ) :: error character ( * ), parameter :: try ( * ) = [ 'mpiexec ' , 'mpirun ' , 'mpiexec.exe' , 'mpirun.exe ' ] character (:), allocatable :: bindir integer :: itri logical :: success ! Try several commands do itri = 1 , size ( try ) call find_command_location ( trim ( try ( itri )), command % s , verbose = verbose , error = error ) if ( allocated ( error )) cycle ! Success! success = len_trim ( command % s ) > 0 if ( success ) then if ( verbose ) print * , '+ runner folder found: ' // command % s command % s = join_path ( command % s , trim ( try ( itri ))) return endif end do ! On windows, also search in %MSMPI_BIN% if ( get_os_type () == OS_WINDOWS ) then ! Check that the runtime is installed bindir = \"\" call get_absolute_path ( get_env ( 'MSMPI_BIN' ), bindir , error ) if ( verbose ) print * , '+ %MSMPI_BIN%=' , bindir ! In some environments, variable %MSMPI_BIN% is missing (i.e. in GitHub Action images). ! Do a second attempt: search for the default location if ( len_trim ( bindir ) <= 0 . or . allocated ( error )) then if ( verbose ) print * , '+ %MSMPI_BIN% empty, searching C:\\Program Files\\Microsoft MPI\\Bin\\ ...' call get_absolute_path ( 'C:\\Program Files\\Microsoft MPI\\Bin\\mpiexec.exe' , bindir , error ) endif if ( len_trim ( bindir ) > 0 . and . . not . allocated ( error )) then ! MSMPI_BIN directory found command % s = join_path ( bindir , 'mpiexec.exe' ) return endif endif ! No valid command found call fatal_error ( error , 'cannot find a valid mpi runner command' ) return end subroutine get_mpi_runner !> Return compiler path subroutine compiler_get_path ( self , path , error ) type ( compiler_t ), intent ( in ) :: self type ( string_t ), intent ( out ) :: path type ( error_t ), allocatable , intent ( out ) :: error call find_command_location ( self % fc , path % s , self % echo , self % verbose , error ) end subroutine compiler_get_path !> Return compiler version subroutine compiler_get_version ( self , version , is_msys2 , error ) type ( compiler_t ), intent ( in ) :: self type ( version_t ), intent ( out ) :: version logical , intent ( out ) :: is_msys2 type ( error_t ), allocatable , intent ( out ) :: error character (:), allocatable :: tmp_file , screen_output , line type ( string_t ) :: ver integer :: stat , iunit , ire , length is_msys2 = . false . select case ( self % id ) case ( id_gcc ) tmp_file = get_temp_filename () call run ( self % fc // \" --version \" , echo = self % echo , verbose = self % verbose , redirect = tmp_file , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'compiler_get_version failed for ' // self % fc ) return end if allocate ( character ( len = 0 ) :: screen_output ) open ( newunit = iunit , file = tmp_file , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit screen_output = screen_output // ' ' // line // ' ' end do ! Close and delete file close ( iunit , status = 'delete' ) else call fatal_error ( error , 'cannot read temporary file from successful compiler_get_version' ) return endif ! Check if this gcc is from the MSYS2 project is_msys2 = index ( screen_output , 'MSYS2' ) > 0 ver = regex_version_from_text ( screen_output , self % fc // ' compiler' , error ) if ( allocated ( error )) return ! Extract version call new_version ( version , ver % s , error ) case default call fatal_error ( error , 'compiler_get_version not yet implemented for compiler ' // self % fc ) return end select end subroutine compiler_get_version !> Initialize an MPI metapackage from a valid wrapper command ('mpif90', etc...) subroutine init_mpi_from_wrappers ( this , compiler , mpilib , fort_wrapper , c_wrapper , cxx_wrapper , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler integer , intent ( in ) :: mpilib type ( string_t ), intent ( in ) :: fort_wrapper , c_wrapper , cxx_wrapper type ( error_t ), allocatable , intent ( out ) :: error type ( version_t ) :: version type ( error_t ), allocatable :: runner_error ! Cleanup structure call destroy ( this ) ! Get linking flags this % link_flags = mpi_wrapper_query ( mpilib , fort_wrapper , 'link' , verbose , error ) if ( allocated ( error )) return ! Remove useless/dangerous flags call filter_link_arguments ( compiler , this % link_flags ) this % has_link_flags = len_trim ( this % link_flags ) > 0 ! Request to use libs in arbitrary order if ( this % has_link_flags . and . compiler % is_gnu () . and . os_is_unix () . and . get_os_type () /= OS_MACOS ) then this % link_flags = string_t ( ' -Wl,--start-group ' // this % link_flags % s ) end if ! Add language-specific flags call set_language_flags ( compiler , mpilib , fort_wrapper , this % has_fortran_flags , this % fflags , verbose , error ) if ( allocated ( error )) return call set_language_flags ( compiler , mpilib , c_wrapper , this % has_c_flags , this % cflags , verbose , error ) if ( allocated ( error )) return call set_language_flags ( compiler , mpilib , cxx_wrapper , this % has_cxx_flags , this % cxxflags , verbose , error ) if ( allocated ( error )) return ! Get library version version = mpi_version_get ( mpilib , fort_wrapper , error ) if ( allocated ( error )) then return else allocate ( this % version , source = version ) end if !> Add default run command, if present this % run_command = mpi_wrapper_query ( mpilib , fort_wrapper , 'runner' , verbose , runner_error ) this % has_run_command = ( len_trim ( this % run_command ) > 0 ) . and . . not . allocated ( runner_error ) contains subroutine set_language_flags ( compiler , mpilib , wrapper , has_flags , flags , verbose , error ) type ( compiler_t ), intent ( in ) :: compiler integer , intent ( in ) :: mpilib type ( string_t ), intent ( in ) :: wrapper logical , intent ( inout ) :: has_flags type ( string_t ), intent ( inout ) :: flags logical , intent ( in ) :: verbose type ( error_t ), allocatable , intent ( out ) :: error ! Get build flags for each language if ( len_trim ( wrapper ) > 0 ) then flags = mpi_wrapper_query ( mpilib , wrapper , 'flags' , verbose , error ) if ( allocated ( error )) return has_flags = len_trim ( flags ) > 0 ! Add heading space flags = string_t ( ' ' // flags % s ) if ( verbose ) print * , '+ MPI language flags from wrapper <' , wrapper % s , '>: flags=' , flags % s call filter_build_arguments ( compiler , flags ) endif end subroutine set_language_flags end subroutine init_mpi_from_wrappers !> Match one of the available compiler wrappers with the current compiler subroutine mpi_compiler_match ( language , wrappers , compiler , which_one , mpilib , error ) integer , intent ( in ) :: language type ( string_t ), intent ( in ) :: wrappers (:) type ( compiler_t ), intent ( in ) :: compiler integer , intent ( out ) :: which_one , mpilib type ( error_t ), allocatable , intent ( out ) :: error integer :: i , same_vendor , vendor_mpilib type ( string_t ) :: screen character ( 128 ) :: msg_out type ( compiler_t ) :: mpi_compiler which_one = 0 same_vendor = 0 mpilib = MPI_TYPE_NONE if ( verbose ) print * , '+ Trying to match available ' , LANG_NAME ( language ), ' MPI wrappers to ' , compiler % fc , '...' do i = 1 , size ( wrappers ) mpilib = which_mpi_library ( wrappers ( i ), compiler , verbose = . false .) screen = mpi_wrapper_query ( mpilib , wrappers ( i ), 'compiler' , verbose = . false ., error = error ) if ( allocated ( error )) return if ( verbose ) print * , ' Wrapper ' , wrappers ( i )% s , ' lib=' , MPI_TYPE_NAME ( mpilib ), ' uses ' , screen % s select case ( language ) case ( LANG_FORTRAN ) ! Build compiler type. The ID is created based on the Fortran name call new_compiler ( mpi_compiler , screen % s , '' , '' , echo = . true ., verbose = . false .) ! Fortran match found! if ( mpi_compiler % id == compiler % id ) then which_one = i return end if case ( LANG_C ) ! For other languages, we can only hope that the name matches the expected one if ( screen % s == compiler % cc . or . screen % s == compiler % fc ) then which_one = i return end if case ( LANG_CXX ) if ( screen % s == compiler % cxx . or . screen % s == compiler % fc ) then which_one = i return end if end select ! Because the intel mpi library does not support llvm_ compiler wrappers yet, ! we must check for that manually if ( is_intel_classic_option ( language , same_vendor , screen , compiler , mpi_compiler )) then same_vendor = i vendor_mpilib = mpilib end if end do ! Intel compiler: if an exact match is not found, attempt closest wrapper if ( which_one == 0 . and . same_vendor > 0 ) then which_one = same_vendor mpilib = vendor_mpilib end if ! None of the available wrappers matched the current Fortran compiler write ( msg_out , 1 ) size ( wrappers ), compiler % fc call fatal_error ( error , trim ( msg_out )) 1 format ( ' None out of ' , i0 , ' valid MPI wrappers matches compiler ' , a ) end subroutine mpi_compiler_match !> Because the Intel mpi library does not support llvm_ compiler wrappers yet, !> we must save the Intel-classic option and later manually replace it logical function is_intel_classic_option ( language , same_vendor_ID , screen_out , compiler , mpi_compiler ) integer , intent ( in ) :: language , same_vendor_ID type ( string_t ), intent ( in ) :: screen_out type ( compiler_t ), intent ( in ) :: compiler , mpi_compiler if ( same_vendor_ID /= 0 ) then is_intel_classic_option = . false . else select case ( language ) case ( LANG_FORTRAN ) is_intel_classic_option = mpi_compiler % is_intel () . and . compiler % is_intel () case ( LANG_C ) is_intel_classic_option = screen_out % s == 'icc' . and . compiler % cc == 'icx' case ( LANG_CXX ) is_intel_classic_option = screen_out % s == 'icpc' . and . compiler % cc == 'icpx' end select end if end function is_intel_classic_option !> Return library version from the MPI wrapper command type ( version_t ) function mpi_version_get ( mpilib , wrapper , error ) integer , intent ( in ) :: mpilib type ( string_t ), intent ( in ) :: wrapper type ( error_t ), allocatable , intent ( out ) :: error type ( string_t ) :: version_line ! Get version string version_line = mpi_wrapper_query ( mpilib , wrapper , 'version' , error = error ) if ( allocated ( error )) return ! Wrap to object call new_version ( mpi_version_get , version_line % s , error ) end function mpi_version_get !> Return several mpi wrappers, and return subroutine mpi_wrappers ( compiler , fort_wrappers , c_wrappers , cpp_wrappers ) type ( compiler_t ), intent ( in ) :: compiler type ( string_t ), allocatable , intent ( out ) :: c_wrappers (:), cpp_wrappers (:), fort_wrappers (:) character ( len = :), allocatable :: mpi_root , intel_wrap type ( error_t ), allocatable :: error ! Attempt gathering MPI wrapper names from the environment variables c_wrappers = [ string_t ( get_env ( 'MPICC' , 'mpicc' ))] cpp_wrappers = [ string_t ( get_env ( 'MPICXX' , 'mpic++' ))] fort_wrappers = [ string_t ( get_env ( 'MPIFC' , 'mpifc' )),& string_t ( get_env ( 'MPIf90' , 'mpif90' )),& string_t ( get_env ( 'MPIf77' , 'mpif77' ))] if ( get_os_type () == OS_WINDOWS ) then c_wrappers = [ c_wrappers , string_t ( 'mpicc.bat' )] cpp_wrappers = [ cpp_wrappers , string_t ( 'mpicxx.bat' )] fort_wrappers = [ fort_wrappers , string_t ( 'mpifc.bat' )] endif ! Add compiler-specific wrappers compiler_specific : select case ( compiler % id ) case ( id_gcc , id_f95 ) c_wrappers = [ c_wrappers , string_t ( 'mpigcc' ), string_t ( 'mpgcc' )] cpp_wrappers = [ cpp_wrappers , string_t ( 'mpig++' ), string_t ( 'mpg++' )] fort_wrappers = [ fort_wrappers , string_t ( 'mpigfortran' ), string_t ( 'mpgfortran' ),& string_t ( 'mpig77' ), string_t ( 'mpg77' )] case ( id_intel_classic_windows , id_intel_llvm_windows , & id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , id_intel_llvm_unknown ) c_wrappers = [ string_t ( get_env ( 'I_MPI_CC' , 'mpiicc' ))] cpp_wrappers = [ string_t ( get_env ( 'I_MPI_CXX' , 'mpiicpc' ))] fort_wrappers = [ string_t ( get_env ( 'I_MPI_F90' , 'mpiifort' ))] ! Also search MPI wrappers via the base MPI folder mpi_root = get_env ( 'I_MPI_ROOT' ) if ( mpi_root /= \"\" ) then mpi_root = join_path ( mpi_root , 'bin' ) intel_wrap = join_path ( mpi_root , 'mpiifort' ) if ( get_os_type () == OS_WINDOWS ) intel_wrap = get_dos_path ( intel_wrap , error ) if ( intel_wrap /= \"\" ) fort_wrappers = [ fort_wrappers , string_t ( intel_wrap )] intel_wrap = join_path ( mpi_root , 'mpiicc' ) if ( get_os_type () == OS_WINDOWS ) intel_wrap = get_dos_path ( intel_wrap , error ) if ( intel_wrap /= \"\" ) c_wrappers = [ c_wrappers , string_t ( intel_wrap )] intel_wrap = join_path ( mpi_root , 'mpiicpc' ) if ( get_os_type () == OS_WINDOWS ) intel_wrap = get_dos_path ( intel_wrap , error ) if ( intel_wrap /= \"\" ) cpp_wrappers = [ cpp_wrappers , string_t ( intel_wrap )] end if case ( id_pgi , id_nvhpc ) c_wrappers = [ c_wrappers , string_t ( 'mpipgicc' ), string_t ( 'mpgcc' )] cpp_wrappers = [ cpp_wrappers , string_t ( 'mpipgic++' )] fort_wrappers = [ fort_wrappers , string_t ( 'mpipgifort' ), string_t ( 'mpipgf90' )] case ( id_cray ) c_wrappers = [ c_wrappers , string_t ( 'cc' )] cpp_wrappers = [ cpp_wrappers , string_t ( 'CC' )] fort_wrappers = [ fort_wrappers , string_t ( 'ftn' )] end select compiler_specific call assert_mpi_wrappers ( fort_wrappers , compiler ) call assert_mpi_wrappers ( c_wrappers , compiler ) call assert_mpi_wrappers ( cpp_wrappers , compiler ) end subroutine mpi_wrappers !> Filter out invalid/unavailable mpi wrappers subroutine assert_mpi_wrappers ( wrappers , compiler , verbose ) type ( string_t ), allocatable , intent ( inout ) :: wrappers (:) type ( compiler_t ), intent ( in ) :: compiler logical , optional , intent ( in ) :: verbose integer :: i integer , allocatable :: works (:) allocate ( works ( size ( wrappers ))) do i = 1 , size ( wrappers ) if ( present ( verbose )) then if ( verbose ) print * , '+ MPI test wrapper <' , wrappers ( i )% s , '>' endif works ( i ) = which_mpi_library ( wrappers ( i ), compiler , verbose ) end do ! Filter out non-working wrappers wrappers = pack ( wrappers , works /= MPI_TYPE_NONE ) end subroutine assert_mpi_wrappers !> Get MPI library type from the wrapper command. Currently, only OpenMPI is supported integer function which_mpi_library ( wrapper , compiler , verbose ) type ( string_t ), intent ( in ) :: wrapper type ( compiler_t ), intent ( in ) :: compiler logical , intent ( in ), optional :: verbose logical :: is_mpi_wrapper integer :: stat ! Init as currently unsupported library which_mpi_library = MPI_TYPE_NONE if ( len_trim ( wrapper ) <= 0 ) return ! Run mpi wrapper first call run_wrapper ( wrapper , verbose = verbose , cmd_success = is_mpi_wrapper ) if ( is_mpi_wrapper ) then if ( compiler % is_intel ()) then which_mpi_library = MPI_TYPE_INTEL return end if ! Attempt to decipher which library this wrapper comes from. ! OpenMPI responds to '--showme' calls call run_wrapper ( wrapper ,[ string_t ( '--showme' )], verbose ,& exitcode = stat , cmd_success = is_mpi_wrapper ) if ( stat == 0 . and . is_mpi_wrapper ) then which_mpi_library = MPI_TYPE_OPENMPI return endif ! MPICH responds to '-show' calls call run_wrapper ( wrapper ,[ string_t ( '-show' )], verbose ,& exitcode = stat , cmd_success = is_mpi_wrapper ) if ( stat == 0 . and . is_mpi_wrapper ) then which_mpi_library = MPI_TYPE_MPICH return endif end if end function which_mpi_library !> Test if an MPI wrapper works type ( string_t ) function mpi_wrapper_query ( mpilib , wrapper , command , verbose , error ) result ( screen ) integer , intent ( in ) :: mpilib type ( string_t ), intent ( in ) :: wrapper character ( * ), intent ( in ) :: command logical , intent ( in ), optional :: verbose type ( error_t ), allocatable , intent ( out ) :: error logical :: success character (:), allocatable :: redirect_str , tokens (:), unsupported_msg type ( string_t ) :: cmdstr type ( compiler_t ) :: mpi_compiler integer :: stat , cmdstat , ire , length unsupported_msg = 'the MPI library of wrapper ' // wrapper % s // ' does not support task ' // trim ( command ) select case ( command ) ! Get MPI compiler name case ( 'compiler' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ); cmdstr = string_t ( '--showme:command' ) case ( MPI_TYPE_MPICH ); cmdstr = string_t ( '-compile-info' ) case ( MPI_TYPE_INTEL ); cmdstr = string_t ( '-show' ) case default call fatal_error ( error , unsupported_msg ) return end select call run_wrapper ( wrapper ,[ cmdstr ], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local ' // MPI_TYPE_NAME ( mpilib ) // & ' library wrapper does not support flag ' // cmdstr % s ) return end if ! Take out the first command from the whole line call remove_newline_characters ( screen ) call split ( screen % s , tokens , delimiters = ' ' ) screen % s = trim ( adjustl ( tokens ( 1 ))) ! Get a list of additional compiler flags case ( 'flags' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ); cmdstr = string_t ( '--showme:compile' ) case ( MPI_TYPE_MPICH ); cmdstr = string_t ( '-compile-info' ) case ( MPI_TYPE_INTEL ); cmdstr = string_t ( '-show' ) case default call fatal_error ( error , unsupported_msg ) return end select call run_wrapper ( wrapper ,[ cmdstr ], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local ' // MPI_TYPE_NAME ( mpilib ) // & ' library wrapper does not support flag ' // cmdstr % s ) return end if ! Post-process output select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) ! This library reports the compiler name only call remove_newline_characters ( screen ) case ( MPI_TYPE_MPICH , MPI_TYPE_INTEL ) ! These libraries report the full command including the compiler name. Remove it if so call remove_newline_characters ( screen ) call split ( screen % s , tokens ) ! Remove trailing compiler name screen % s = screen % s ( len_trim ( tokens ( 1 )) + 1 :) case default call fatal_error ( error , 'invalid MPI library type' ) return end select ! Get a list of additional linker flags case ( 'link' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ); cmdstr = string_t ( '--showme:link' ) case ( MPI_TYPE_MPICH ); cmdstr = string_t ( '-link-info' ) case ( MPI_TYPE_INTEL ); cmdstr = string_t ( '-show' ) case default call fatal_error ( error , unsupported_msg ) return end select call run_wrapper ( wrapper ,[ cmdstr ], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local ' // MPI_TYPE_NAME ( mpilib ) // & ' library wrapper does not support flag ' // cmdstr % s ) return end if select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) call remove_newline_characters ( screen ) case ( MPI_TYPE_MPICH , MPI_TYPE_INTEL ) ! MPICH reports the full command including the compiler name. Remove it if so call remove_newline_characters ( screen ) call split ( screen % s , tokens ) ! Remove trailing compiler name screen % s = screen % s ( len_trim ( tokens ( 1 )) + 1 :) case default call fatal_error ( error , unsupported_msg ) return end select ! Get a list of MPI library directories case ( 'link_dirs' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) ! --showme:command returns the build command of this wrapper call run_wrapper ( wrapper ,[ string_t ( '--showme:libdirs' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local OpenMPI library does not support --showme:libdirs' ) return end if case default call fatal_error ( error , unsupported_msg ) return end select ! Get a list of include directories for the MPI headers/modules case ( 'incl_dirs' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) ! --showme:command returns the build command of this wrapper call run_wrapper ( wrapper ,[ string_t ( '--showme:incdirs' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local OpenMPI library does not support --showme:incdirs' ) return end if case default call fatal_error ( error , unsupported_msg ) return end select call remove_newline_characters ( screen ) ! Retrieve library version case ( 'version' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) ! --showme:command returns the build command of this wrapper call run_wrapper ( wrapper ,[ string_t ( '--showme:version' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local OpenMPI library does not support --showme:version' ) return else call remove_newline_characters ( screen ) end if case ( MPI_TYPE_MPICH ) !> MPICH offers command \"mpichversion\" in the same system folder as the MPI wrappers. !> So, attempt to run that first cmdstr = string_t ( 'mpichversion' ) call run_wrapper ( cmdstr , verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) ! Second option: run mpich wrapper + \"-v\" if ( stat /= 0 . or . . not . success ) then call run_wrapper ( wrapper ,[ string_t ( '-v' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) call remove_newline_characters ( screen ) endif ! Third option: mpiexec --version if ( stat /= 0 . or . . not . success ) then cmdstr = string_t ( 'mpiexec --version' ) call run_wrapper ( cmdstr , verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) endif if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'cannot retrieve MPICH library version from ' ) return end if case ( MPI_TYPE_INTEL ) ! --showme:command returns the build command of this wrapper call run_wrapper ( wrapper ,[ string_t ( '-v' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local INTEL MPI library does not support -v' ) return else call remove_newline_characters ( screen ) end if case default call fatal_error ( error , unsupported_msg ) return end select ! Extract version screen = regex_version_from_text ( screen % s , MPI_TYPE_NAME ( mpilib ) // ' library' , error ) if ( allocated ( error )) return ! Get path to the MPI runner command case ( 'runner' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI , MPI_TYPE_MPICH , MPI_TYPE_MSMPI , MPI_TYPE_INTEL ) call get_mpi_runner ( screen , verbose , error ) case default call fatal_error ( error , unsupported_msg ) return end select case default ; call fatal_error ( error , 'an invalid MPI wrapper command (' // command // & ') was invoked for wrapper <' // wrapper % s // '>.' ) return end select end function mpi_wrapper_query !> Check if input is a useful linker argument logical function is_link_argument ( compiler , string ) type ( compiler_t ), intent ( in ) :: compiler character ( * ), intent ( in ) :: string select case ( compiler % id ) case ( id_intel_classic_windows , id_intel_llvm_windows ) is_link_argument = string == '/link' & . or . str_begins_with_str ( string , '/LIBPATH' )& . or . str_ends_with ( string , '.lib' ) ! always .lib whether static or dynamic case default ! fix OpenMPI's Fortran wrapper bug (https://github.com/open-mpi/ompi/issues/11636) here is_link_argument = ( str_begins_with_str ( string , '-L' ) & . or . str_begins_with_str ( string , '-l' ) & . or . str_begins_with_str ( string , '-Xlinker' ) & . or . string == '-pthread' & . or . ( str_begins_with_str ( string , '-W' ) . and . & ( string /= '-Wall' ) . and . (. not . str_begins_with_str ( string , '-Werror' ))) ) & . and . . not . ( & ( get_os_type () == OS_MACOS . and . index ( string , '-commons,use_dylibs' ) > 0 ) ) end select end function is_link_argument !> From build, remove optimization and other unnecessary flags subroutine filter_build_arguments ( compiler , command ) type ( compiler_t ), intent ( in ) :: compiler type ( string_t ), intent ( inout ) :: command character ( len = :), allocatable :: tokens (:) integer :: i , n , re_i , re_l logical , allocatable :: keep (:) logical :: keep_next character ( len = :), allocatable :: module_flag , include_flag if ( len_trim ( command ) <= 0 ) return ! Split command into arguments tokens = shlex_split ( command % s ) module_flag = get_module_flag ( compiler , \"\" ) include_flag = get_include_flag ( compiler , \"\" ) n = size ( tokens ) allocate ( keep ( n ), source = . false .) keep_next = . false . do i = 1 , n if ( get_os_type () == OS_MACOS . and . index ( tokens ( i ), '-commons,use_dylibs' ) > 0 ) then keep ( i ) = . false . keep_next = . false . elseif ( str_begins_with_str ( tokens ( i ), '-D' ) . or . & str_begins_with_str ( tokens ( i ), '-f' ) . or . & str_begins_with_str ( tokens ( i ), '-I' ) . or . & str_begins_with_str ( tokens ( i ), module_flag ) . or . & str_begins_with_str ( tokens ( i ), include_flag ) . or . & tokens ( i ) == '-pthread' . or . & ( str_begins_with_str ( tokens ( i ), '-W' ) . and . tokens ( i ) /= '-Wall' . and . . not . str_begins_with_str ( tokens ( i ), '-Werror' )) & ) then keep ( i ) = . true . if ( tokens ( i ) == module_flag . or . tokens ( i ) == include_flag . or . tokens ( i ) == '-I' ) keep_next = . true . elseif ( keep_next ) then keep ( i ) = . true . keep_next = . false . end if end do ! Backfill command = string_t ( \"\" ) do i = 1 , n if (. not . keep ( i )) cycle command % s = command % s // ' ' // trim ( tokens ( i )) end do end subroutine filter_build_arguments !> From the linker flags, remove optimization and other unnecessary flags subroutine filter_link_arguments ( compiler , command ) type ( compiler_t ), intent ( in ) :: compiler type ( string_t ), intent ( inout ) :: command character ( len = :), allocatable :: tokens (:) integer :: i , n logical , allocatable :: keep (:) logical :: keep_next if ( len_trim ( command ) <= 0 ) return ! Split command into arguments tokens = shlex_split ( command % s ) n = size ( tokens ) allocate ( keep ( n ), source = . false .) keep_next = . false . do i = 1 , n if ( is_link_argument ( compiler , tokens ( i ))) then keep ( i ) = . true . if ( tokens ( i ) == '-L' . or . tokens ( i ) == '-Xlinker' ) keep_next = . true . elseif ( keep_next ) then keep ( i ) = . true . keep_next = . false . end if end do ! Backfill command = string_t ( \"\" ) do i = 1 , n if (. not . keep ( i )) cycle command % s = command % s // ' ' // trim ( tokens ( i )) end do end subroutine filter_link_arguments !> Given a library name and folder, find extension and prefix subroutine lib_get_trailing ( lib_name , lib_dir , prefix , suffix , found ) character ( * ), intent ( in ) :: lib_name , lib_dir character (:), allocatable , intent ( out ) :: prefix , suffix logical , intent ( out ) :: found character ( * ), parameter :: extensions ( * ) = [ character ( 11 ) :: '.dll.a' , '.a' , '.dylib' , '.dll' ] logical :: is_file character (:), allocatable :: noext , tokens (:), path integer :: l , k ! Extract name with no extension call split ( lib_name , tokens , '.' ) noext = trim ( tokens ( 1 )) ! Get library extension: find file name: NAME.a, NAME.dll.a, NAME.dylib, libNAME.a, etc. found = . false . suffix = \"\" prefix = \"\" with_pref : do l = 1 , 2 if ( l == 2 ) then prefix = \"lib\" else prefix = \"\" end if find_ext : do k = 1 , size ( extensions ) path = join_path ( lib_dir , prefix // noext // trim ( extensions ( k ))) inquire ( file = path , exist = is_file ) if ( is_file ) then suffix = trim ( extensions ( k )) found = . true . exit with_pref end if end do find_ext end do with_pref if (. not . found ) then prefix = \"\" suffix = \"\" end if end subroutine lib_get_trailing !> Initialize HDF5 metapackage for the current system subroutine init_hdf5 ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error character ( * ), parameter :: find_hl ( * ) = & [ character ( 11 ) :: '_hl_fortran' , 'hl_fortran' , '_fortran' , '_hl' ] character ( * ), parameter :: candidates ( * ) = & [ character ( 15 ) :: 'hdf5_hl_fortran' , 'hdf5-hl-fortran' , 'hdf5_fortran' , 'hdf5-fortran' ,& 'hdf5_hl' , 'hdf5' , 'hdf5-serial' ] integer :: i , j , k , l logical :: s , found_hl ( size ( find_hl )), found type ( string_t ) :: log , this_lib type ( string_t ), allocatable :: libs (:), flags (:), modules (:), non_fortran (:) character ( len = :), allocatable :: name , module_flag , include_flag , libdir , ext , pref module_flag = get_module_flag ( compiler , \"\" ) include_flag = get_include_flag ( compiler , \"\" ) !> Cleanup call destroy ( this ) allocate ( this % link_libs ( 0 ), this % incl_dirs ( 0 ), this % external_modules ( 0 ), non_fortran ( 0 )) this % link_flags = string_t ( \"\" ) this % flags = string_t ( \"\" ) !> Assert pkg-config is installed if (. not . assert_pkg_config ()) then call fatal_error ( error , 'hdf5 metapackage requires pkg-config' ) return end if !> Find pkg-config package file by priority name = 'NOT_FOUND' find_package : do i = 1 , size ( candidates ) if ( pkgcfg_has_package ( trim ( candidates ( i )))) then name = trim ( candidates ( i )) exit find_package end if end do find_package !> some distros put hdf5-1.2.3.pc with version number in .pc filename. if ( name == 'NOT_FOUND' ) then modules = pkgcfg_list_all ( error ) find_global_package : do i = 1 , size ( modules ) if ( str_begins_with_str ( modules ( i )% s , 'hdf5' )) then name = modules ( i )% s exit find_global_package end if end do find_global_package end if if ( name == 'NOT_FOUND' ) then call fatal_error ( error , 'pkg-config could not find a suitable hdf5 package.' ) return end if !> Get version log = pkgcfg_get_version ( name , error ) if ( allocated ( error )) return allocate ( this % version ) call new_version ( this % version , log % s , error ) if ( allocated ( error )) return !> Get libraries libs = pkgcfg_get_libs ( name , error ) if ( allocated ( error )) return libdir = \"\" do i = 1 , size ( libs ) if ( str_begins_with_str ( libs ( i )% s , '-l' )) then this % has_link_libraries = . true . this % link_libs = [ this % link_libs , string_t ( libs ( i )% s ( 3 :))] else ! -L and others: concatenate this % has_link_flags = . true . this % link_flags = string_t ( trim ( this % link_flags % s ) // ' ' // libs ( i )% s ) ! Also save library dir if ( str_begins_with_str ( libs ( i )% s , '-L' )) then libdir = libs ( i )% s ( 3 :) elseif ( str_begins_with_str ( libs ( i )% s , '/LIBPATH' )) then libdir = libs ( i )% s ( 9 :) endif end if end do ! Some pkg-config hdf5.pc (e.g. Ubuntu) don't include the commonly-used HL HDF5 libraries, ! so let's add them if they exist if ( len_trim ( libdir ) > 0 ) then do i = 1 , size ( this % link_libs ) found_hl = . false . if (. not . str_ends_with ( this % link_libs ( i )% s , find_hl )) then ! Extract name with no extension call lib_get_trailing ( this % link_libs ( i )% s , libdir , pref , ext , found ) ! Search how many versions with the Fortran endings there are finals : do k = 1 , size ( find_hl ) do j = 1 , size ( this % link_libs ) if ( str_begins_with_str ( this % link_libs ( j )% s , this % link_libs ( i )% s ) . and . & str_ends_with ( this % link_libs ( j )% s , trim ( find_hl ( k )))) then found_hl ( k ) = . true . cycle finals end if end do end do finals ! For each of the missing ones, if there is a file, add it add_missing : do k = 1 , size ( find_hl ) if ( found_hl ( k )) cycle add_missing ! Build file name this_lib % s = join_path ( libdir , pref // this % link_libs ( i )% s // trim ( find_hl ( k )) // ext ) inquire ( file = this_lib % s , exist = found ) ! File exists, but it is not linked against if ( found ) this % link_libs = [ this % link_libs , & string_t ( this % link_libs ( i )% s // trim ( find_hl ( k )))] end do add_missing end if end do endif !> Get compiler flags flags = pkgcfg_get_build_flags ( name ,. true ., error ) if ( allocated ( error )) return do i = 1 , size ( flags ) if ( str_begins_with_str ( flags ( i )% s , include_flag )) then this % has_include_dirs = . true . this % incl_dirs = [ this % incl_dirs , string_t ( flags ( i )% s ( len ( include_flag ) + 1 :))] else this % has_build_flags = . true . this % flags = string_t ( trim ( this % flags % s ) // ' ' // flags ( i )% s ) end if end do !> Add HDF5 modules as external this % has_external_modules = . true . this % external_modules = [ string_t ( 'h5a' ), & string_t ( 'h5d' ), & string_t ( 'h5es' ), & string_t ( 'h5e' ), & string_t ( 'h5f' ), & string_t ( 'h5g' ), & string_t ( 'h5i' ), & string_t ( 'h5l' ), & string_t ( 'h5o' ), & string_t ( 'h5p' ), & string_t ( 'h5r' ), & string_t ( 'h5s' ), & string_t ( 'h5t' ), & string_t ( 'h5vl' ), & string_t ( 'h5z' ), & string_t ( 'h5lib' ), & string_t ( 'h5global' ), & string_t ( 'h5_gen' ), & string_t ( 'h5fortkit' ), & string_t ( 'hdf5' )] end subroutine init_hdf5 end module fpm_meta","tags":"","loc":"sourcefile/fpm_meta.f90.html"},{"title":"fpm_backend.F90 – Fortran-lang/fpm","text":"Source Code !># Build backend !> Uses a list of `[[build_target_ptr]]` and a valid `[[fpm_model]]` instance !> to schedule and execute the compilation and linking of package targets. !> !> The package build process (`[[build_package]]`) comprises three steps: !> !> 1. __Target sorting:__ topological sort of the target dependency graph (`[[sort_target]]`) !> 2. __Target scheduling:__ group targets into schedule regions based on the sorting (`[[schedule_targets]]`) !> 3. __Target building:__ generate targets by compilation or linking !> !> @note If compiled with OpenMP, targets will be build in parallel where possible. !> !>### Incremental compilation !> The backend process supports *incremental* compilation whereby targets are not !> re-compiled if their corresponding dependencies have not been modified. !> !> - Source-based targets (*i.e.* objects) are not re-compiled if the corresponding source !> file is unmodified AND all of the target dependencies are not marked for re-compilation !> !> - Link targets (*i.e.* executables and libraries) are not re-compiled if the !> target output file already exists AND all of the target dependencies are not marked for !> re-compilation !> !> Source file modification is determined by a file digest (hash) which is calculated during !> the source parsing phase ([[fpm_source_parsing]]) and cached to disk after a target is !> successfully generated. !> module fpm_backend use , intrinsic :: iso_fortran_env , only : stdin => input_unit , stdout => output_unit , stderr => error_unit use fpm_error , only : fpm_stop use fpm_filesystem , only : basename , dirname , join_path , exists , mkdir , run , getline use fpm_model , only : fpm_model_t use fpm_strings , only : string_t , operator (. in .) use fpm_targets , only : build_target_t , build_target_ptr , FPM_TARGET_OBJECT , & FPM_TARGET_C_OBJECT , FPM_TARGET_ARCHIVE , FPM_TARGET_EXECUTABLE , & FPM_TARGET_CPP_OBJECT use fpm_backend_output implicit none private public :: build_package , sort_target , schedule_targets #ifndef FPM_BOOTSTRAP interface function c_isatty () bind ( C , name = 'c_isatty' ) use , intrinsic :: iso_c_binding , only : c_int integer ( c_int ) :: c_isatty end function end interface #endif contains !> Top-level routine to build package described by `model` subroutine build_package ( targets , model , verbose ) type ( build_target_ptr ), intent ( inout ) :: targets (:) type ( fpm_model_t ), intent ( in ) :: model logical , intent ( in ) :: verbose integer :: i , j type ( build_target_ptr ), allocatable :: queue (:) integer , allocatable :: schedule_ptr (:), stat (:) logical :: build_failed , skip_current type ( string_t ), allocatable :: build_dirs (:) type ( string_t ) :: temp type ( build_progress_t ) :: progress logical :: plain_output ! Need to make output directory for include (mod) files allocate ( build_dirs ( 0 )) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( target % output_dir . in . build_dirs ) cycle temp % s = target % output_dir build_dirs = [ build_dirs , temp ] end associate end do do i = 1 , size ( build_dirs ) call mkdir ( build_dirs ( i )% s , verbose ) end do ! Perform depth-first topological sort of targets do i = 1 , size ( targets ) call sort_target ( targets ( i )% ptr ) end do ! Construct build schedule queue call schedule_targets ( queue , schedule_ptr , targets ) ! Check if queue is empty if (. not . verbose . and . size ( queue ) < 1 ) then write ( stderr , '(a)' ) 'Project is up to date' return end if ! Initialise build status flags allocate ( stat ( size ( queue ))) stat (:) = 0 build_failed = . false . ! Set output mode #ifndef FPM_BOOTSTRAP plain_output = (. not .( c_isatty () == 1 )) . or . verbose #else plain_output = . true . #endif progress = build_progress_t ( queue , plain_output ) ! Loop over parallel schedule regions do i = 1 , size ( schedule_ptr ) - 1 ! Build targets in schedule region i !$omp parallel do default(shared) private(skip_current) schedule(dynamic,1) do j = schedule_ptr ( i ),( schedule_ptr ( i + 1 ) - 1 ) ! Check if build already failed !$omp atomic read skip_current = build_failed if (. not . skip_current ) then call progress % compiling_status ( j ) call build_target ( model , queue ( j )% ptr , verbose , stat ( j )) call progress % completed_status ( j , stat ( j )) end if ! Set global flag if this target failed to build if ( stat ( j ) /= 0 ) then !$omp atomic write build_failed = . true . end if end do ! Check if this schedule region failed: exit with message if failed if ( build_failed ) then write ( * , * ) do j = 1 , size ( stat ) if ( stat ( j ) /= 0 ) Then call print_build_log ( queue ( j )% ptr ) end if end do do j = 1 , size ( stat ) if ( stat ( j ) /= 0 ) then write ( stderr , '(*(g0:,1x))' ) ' Compilation failed for object \"' , basename ( queue ( j )% ptr % output_file ), '\"' end if end do call fpm_stop ( 1 , 'stopping due to failed compilation' ) end if end do call progress % success () end subroutine build_package !> Topologically sort a target for scheduling by !> recursing over its dependencies. !> !> Checks disk-cached source hashes to determine if objects are !> up-to-date. Up-to-date sources are tagged as skipped. !> !> On completion, `target` should either be marked as !> sorted (`target%sorted=.true.`) or skipped (`target%skip=.true.`) !> !> If `target` is marked as sorted, `target%schedule` should be an !> integer greater than zero indicating the region for scheduling !> recursive subroutine sort_target ( target ) type ( build_target_t ), intent ( inout ), target :: target integer :: i , fh , stat ! Check if target has already been processed (as a dependency) if ( target % sorted . or . target % skip ) then return end if ! Check for a circular dependency ! (If target has been touched but not processed) if ( target % touched ) then call fpm_stop ( 1 , '(!) Circular dependency found with: ' // target % output_file ) else target % touched = . true . ! Set touched flag end if ! Load cached source file digest if present if (. not . allocated ( target % digest_cached ) . and . & exists ( target % output_file ) . and . & exists ( target % output_file // '.digest' )) then allocate ( target % digest_cached ) open ( newunit = fh , file = target % output_file // '.digest' , status = 'old' ) read ( fh , * , iostat = stat ) target % digest_cached close ( fh ) if ( stat /= 0 ) then ! Cached digest is not recognized deallocate ( target % digest_cached ) end if end if if ( allocated ( target % source )) then ! Skip if target is source-based and source file is unmodified if ( allocated ( target % digest_cached )) then if ( target % digest_cached == target % source % digest ) target % skip = . true . end if elseif ( exists ( target % output_file )) then ! Skip if target is not source-based and already exists target % skip = . true . end if ! Loop over target dependencies target % schedule = 1 do i = 1 , size ( target % dependencies ) ! Sort dependency call sort_target ( target % dependencies ( i )% ptr ) if (. not . target % dependencies ( i )% ptr % skip ) then ! Can't skip target if any dependency is not skipped target % skip = . false . ! Set target schedule after all of its dependencies target % schedule = max ( target % schedule , target % dependencies ( i )% ptr % schedule + 1 ) end if end do ! Mark flag as processed: either sorted or skipped target % sorted = . not . target % skip end subroutine sort_target !> Construct a build schedule from the sorted targets. !> !> The schedule is broken into regions, described by `schedule_ptr`, !> where targets in each region can be compiled in parallel. !> subroutine schedule_targets ( queue , schedule_ptr , targets ) type ( build_target_ptr ), allocatable , intent ( out ) :: queue (:) integer , allocatable :: schedule_ptr (:) type ( build_target_ptr ), intent ( in ) :: targets (:) integer :: i , j integer :: n_schedule , n_sorted n_schedule = 0 ! Number of schedule regions n_sorted = 0 ! Total number of targets to build do i = 1 , size ( targets ) if ( targets ( i )% ptr % sorted ) then n_sorted = n_sorted + 1 end if n_schedule = max ( n_schedule , targets ( i )% ptr % schedule ) end do allocate ( queue ( n_sorted )) allocate ( schedule_ptr ( n_schedule + 1 )) ! Construct the target queue and schedule region pointer n_sorted = 1 schedule_ptr ( n_sorted ) = 1 do i = 1 , n_schedule do j = 1 , size ( targets ) if ( targets ( j )% ptr % sorted ) then if ( targets ( j )% ptr % schedule == i ) then queue ( n_sorted )% ptr => targets ( j )% ptr n_sorted = n_sorted + 1 end if end if end do schedule_ptr ( i + 1 ) = n_sorted end do end subroutine schedule_targets !> Call compile/link command for a single target. !> !> If successful, also caches the source file digest to disk. !> subroutine build_target ( model , target , verbose , stat ) type ( fpm_model_t ), intent ( in ) :: model type ( build_target_t ), intent ( in ), target :: target logical , intent ( in ) :: verbose integer , intent ( out ) :: stat integer :: fh !$omp critical if (. not . exists ( dirname ( target % output_file ))) then call mkdir ( dirname ( target % output_file ), verbose ) end if !$omp end critical select case ( target % target_type ) case ( FPM_TARGET_OBJECT ) call model % compiler % compile_fortran ( target % source % file_name , target % output_file , & & target % compile_flags , target % output_log_file , stat ) case ( FPM_TARGET_C_OBJECT ) call model % compiler % compile_c ( target % source % file_name , target % output_file , & & target % compile_flags , target % output_log_file , stat ) case ( FPM_TARGET_CPP_OBJECT ) call model % compiler % compile_cpp ( target % source % file_name , target % output_file , & & target % compile_flags , target % output_log_file , stat ) case ( FPM_TARGET_EXECUTABLE ) call model % compiler % link ( target % output_file , & & target % compile_flags // \" \" // target % link_flags , target % output_log_file , stat ) case ( FPM_TARGET_ARCHIVE ) call model % archiver % make_archive ( target % output_file , target % link_objects , & & target % output_log_file , stat ) end select if ( stat == 0 . and . allocated ( target % source )) then open ( newunit = fh , file = target % output_file // '.digest' , status = 'unknown' ) write ( fh , * ) target % source % digest close ( fh ) end if end subroutine build_target !> Read and print the build log for target !> subroutine print_build_log ( target ) type ( build_target_t ), intent ( in ), target :: target integer :: fh , ios character (:), allocatable :: line if ( exists ( target % output_log_file )) then open ( newunit = fh , file = target % output_log_file , status = 'old' ) do call getline ( fh , line , ios ) if ( ios /= 0 ) exit write ( * , '(A)' ) trim ( line ) end do close ( fh ) else write ( stderr , '(*(g0:,1x))' ) ' Unable to find build log \"' , basename ( target % output_log_file ), '\"' end if end subroutine print_build_log end module fpm_backend","tags":"","loc":"sourcefile/fpm_backend.f90.html"},{"title":"git.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation for interacting with git repositories. module fpm_git use fpm_error , only : error_t , fatal_error use fpm_filesystem , only : get_temp_filename , getline , join_path , execute_and_read_output , run use fpm_toml , only : serializable_t , toml_table , get_value , set_value , toml_stat , set_string implicit none public :: git_target_t , git_target_default , git_target_branch , git_target_tag , git_target_revision , git_revision , & & git_archive , git_matches_manifest , operator ( == ), compressed_package_name !> Name of the compressed package that is generated temporarily. character ( len =* ), parameter :: compressed_package_name = 'compressed_package' !> Possible git target type :: enum_descriptor !> Default target integer :: default = 200 !> Branch in git repository integer :: branch = 201 !> Tag in git repository integer :: tag = 202 !> Commit hash integer :: revision = 203 !> Invalid descriptor integer :: error = - 999 end type enum_descriptor !> Actual enumerator for descriptors type ( enum_descriptor ), parameter :: git_descriptor = enum_descriptor () !> Description of an git target type , extends ( serializable_t ) :: git_target_t !> Kind of the git target integer :: descriptor = git_descriptor % default !> Target URL of the git repository character ( len = :), allocatable :: url !> Additional descriptor of the git object character ( len = :), allocatable :: object contains !> Fetch and checkout in local directory procedure :: checkout !> Show information on instance procedure :: info !> Serialization interface procedure :: serializable_is_same => git_is_same procedure :: dump_to_toml procedure :: load_from_toml end type git_target_t !> Common output format for writing to the command line character ( len =* ), parameter :: out_fmt = '(\"#\", *(1x, g0))' contains !> Default target function git_target_default ( url ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % default self % url = url end function git_target_default !> Target a branch in the git repository function git_target_branch ( url , branch ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Name of the branch of interest character ( len =* ), intent ( in ) :: branch !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % branch self % url = url self % object = branch end function git_target_branch !> Target a specific git revision function git_target_revision ( url , sha1 ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Commit hash of interest character ( len =* ), intent ( in ) :: sha1 !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % revision self % url = url self % object = sha1 end function git_target_revision !> Target a git tag function git_target_tag ( url , tag ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Tag name of interest character ( len =* ), intent ( in ) :: tag !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % tag self % url = url self % object = tag end function git_target_tag !> Check that two git targets are equal logical function git_is_same ( this , that ) class ( git_target_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that git_is_same = . false . select type ( other => that ) type is ( git_target_t ) if (. not .( this % descriptor == other % descriptor )) return if (. not .( this % url == other % url )) return if (. not .( this % object == other % object )) return class default ! Not the same type return end select !> All checks passed! git_is_same = . true . end function git_is_same !> Check that a cached dependency matches a manifest request logical function git_matches_manifest ( cached , manifest , verbosity , iunit ) !> Two input git targets type ( git_target_t ), intent ( in ) :: cached , manifest integer , intent ( in ) :: verbosity , iunit git_matches_manifest = cached % url == manifest % url if (. not . git_matches_manifest ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT URL has changed: \" , cached % url , \" vs. \" , manifest % url return endif !> The manifest dependency only contains partial information (what's requested), !> while the cached dependency always stores a commit hash because it's built !> after the repo is available (saved as git_descriptor%revision==revision). !> So, comparing against the descriptor is not reliable git_matches_manifest = allocated ( cached % object ) . eqv . allocated ( manifest % object ) if ( git_matches_manifest . and . allocated ( cached % object )) & git_matches_manifest = cached % object == manifest % object if (. not . git_matches_manifest ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT OBJECT has changed: \" , cached % object , \" vs. \" , manifest % object end if end function git_matches_manifest subroutine checkout ( self , local_path , error ) !> Instance of the git target class ( git_target_t ), intent ( in ) :: self !> Local path to checkout in character ( * ), intent ( in ) :: local_path !> Error type ( error_t ), allocatable , intent ( out ) :: error integer :: stat character ( len = :), allocatable :: object , workdir if ( allocated ( self % object )) then object = self % object else object = 'HEAD' end if workdir = \"--work-tree=\" // local_path // \" --git-dir=\" // join_path ( local_path , \".git\" ) call execute_command_line ( \"git init \" // local_path , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while initiating git repository for remote dependency' ) return end if call execute_command_line ( \"git \" // workdir // \" fetch --depth=1 \" // & self % url // \" \" // object , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while fetching git repository for remote dependency' ) return end if call execute_command_line ( \"git \" // workdir // \" checkout -qf FETCH_HEAD\" , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while checking out git repository for remote dependency' ) return end if end subroutine checkout subroutine git_revision ( local_path , object , error ) !> Local path to checkout in character ( * ), intent ( in ) :: local_path !> Git object reference character ( len = :), allocatable , intent ( out ) :: object !> Error type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , unit , istart , iend character ( len = :), allocatable :: temp_file , line , iomsg , workdir character ( len =* ), parameter :: hexdigits = '0123456789abcdef' workdir = \"--work-tree=\" // local_path // \" --git-dir=\" // join_path ( local_path , \".git\" ) allocate ( temp_file , source = get_temp_filename ()) line = \"git \" // workdir // \" log -n 1 > \" // temp_file call execute_command_line ( line , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error while retrieving commit information\" ) return end if open ( file = temp_file , newunit = unit ) call getline ( unit , line , stat , iomsg ) if ( stat /= 0 ) then call fatal_error ( error , iomsg ) return end if close ( unit , status = \"delete\" ) ! Tokenize: ! commit 0123456789abcdef (HEAD, ...) istart = scan ( line , ' ' ) + 1 iend = verify ( line ( istart :), hexdigits ) + istart - 1 if ( iend < istart ) iend = len ( line ) object = line ( istart : iend ) end subroutine git_revision !> Show information on git target subroutine info ( self , unit , verbosity ) !> Instance of the git target class ( git_target_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Git target\" if ( allocated ( self % url )) then write ( unit , fmt ) \"- URL\" , self % url end if if ( allocated ( self % object )) then select case ( self % descriptor ) case default write ( unit , fmt ) \"- object\" , self % object case ( git_descriptor % tag ) write ( unit , fmt ) \"- tag\" , self % object case ( git_descriptor % branch ) write ( unit , fmt ) \"- branch\" , self % object case ( git_descriptor % revision ) write ( unit , fmt ) \"- sha1\" , self % object end select end if end subroutine info !> Dump dependency to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( git_target_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_string ( table , \"descriptor\" , descriptor_name ( self % descriptor ), error , 'git_target_t' ) if ( allocated ( error )) return call set_string ( table , \"url\" , self % url , error , 'git_target_t' ) if ( allocated ( error )) return call set_string ( table , \"object\" , self % object , error , 'git_target_t' ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( git_target_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: descriptor_name call get_value ( table , \"descriptor\" , descriptor_name ) self % descriptor = parse_descriptor ( descriptor_name ) if ( self % descriptor == git_descriptor % error ) then call fatal_error ( error , \"invalid descriptor ID <\" // descriptor_name // \"> in TOML entry\" ) return end if !> Target URL of the git repository call get_value ( table , \"url\" , self % url ) !> Additional descriptor of the git object call get_value ( table , \"object\" , self % object ) end subroutine load_from_toml !> Parse git descriptor identifier from a string pure integer function parse_descriptor ( name ) character ( len =* ), intent ( in ) :: name select case ( name ) case ( \"default\" ); parse_descriptor = git_descriptor % default case ( \"branch\" ); parse_descriptor = git_descriptor % branch case ( \"tag\" ); parse_descriptor = git_descriptor % tag case ( \"revision\" ); parse_descriptor = git_descriptor % revision case default ; parse_descriptor = git_descriptor % error end select end function parse_descriptor !> Code git descriptor to a string pure function descriptor_name ( descriptor ) result ( name ) integer , intent ( in ) :: descriptor character ( len = :), allocatable :: name select case ( descriptor ) case ( git_descriptor % default ); name = \"default\" case ( git_descriptor % branch ); name = \"branch\" case ( git_descriptor % tag ); name = \"tag\" case ( git_descriptor % revision ); name = \"revision\" case default ; name = \"ERROR\" end select end function descriptor_name !> Archive a folder using `git archive`. subroutine git_archive ( source , destination , ref , additional_files , verbose , error ) !> Directory to archive. character ( * ), intent ( in ) :: source !> Destination of the archive. character ( * ), intent ( in ) :: destination !> (Symbolic) Reference to be archived. character ( * ), intent ( in ) :: ref !> (Optional) list of additional untracked files to be added to the archive. character ( * ), optional , intent ( in ) :: additional_files (:) !> Print additional information if true. logical , intent ( in ) :: verbose !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , i character ( len = :), allocatable :: cmd_output , archive_format , add_files call execute_and_read_output ( 'git archive -l' , cmd_output , error , verbose ) if ( allocated ( error )) return if ( index ( cmd_output , 'tar.gz' ) /= 0 ) then archive_format = 'tar.gz' else call fatal_error ( error , \"Cannot find a suitable archive format for 'git archive'.\" ); return end if allocate ( character ( len = 0 ) :: add_files ) if ( present ( additional_files )) then do i = 1 , size ( additional_files ) add_files = trim ( add_files ) // ' --add-file=' // adjustl ( additional_files ( i )) end do endif call run ( 'git archive ' // ref // ' & & --format=' // archive_format // & & add_files // ' & & -o ' // destination , & & echo = verbose , & & exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error packing '\" // source // \"'.\" ); return end if end end module fpm_git","tags":"","loc":"sourcefile/git.f90.html"},{"title":"dependency.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for dependencies. !> !> A dependency table can currently have the following fields !> !>```toml !>[dependencies] !>\"dep1\" = { git = \"url\" } !>\"dep2\" = { git = \"url\", branch = \"name\" } !>\"dep3\" = { git = \"url\", tag = \"name\" } !>\"dep4\" = { git = \"url\", rev = \"sha1\" } !>\"dep0\" = { path = \"path\" } !>``` !> !> To reduce the amount of boilerplate code this module provides two constructors !> for dependency types, one basic for an actual dependency (inline) table !> and another to collect all dependency objects from a dependencies table, !> which is handling the allocation of the objects and is forwarding the !> individual dependency tables to their respective constructors. !> The usual entry point should be the constructor for the super table. !> !> This objects contains a target to retrieve required `fpm` projects to !> build the target declaring the dependency. !> Resolving a dependency will result in obtaining a new package configuration !> data for the respective project. module fpm_manifest_dependency use fpm_error , only : error_t , syntax_error , fatal_error use fpm_git , only : git_target_t , git_target_tag , git_target_branch , & & git_target_revision , git_target_default , git_matches_manifest use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , check_keys , serializable_t , add_table , & & set_value , set_string use fpm_filesystem , only : windows_path , join_path use fpm_environment , only : get_os_type , OS_WINDOWS use fpm_manifest_metapackages , only : metapackage_config_t , is_meta_package , new_meta_config , & metapackage_request_t , new_meta_request use fpm_versioning , only : version_t , new_version use fpm_strings , only : string_t use fpm_manifest_preprocess implicit none private public :: dependency_config_t , new_dependency , new_dependencies , manifest_has_changed , & & dependency_destroy , resize !> Configuration meta data for a dependency type , extends ( serializable_t ) :: dependency_config_t !> Name of the dependency character ( len = :), allocatable :: name !> Local target character ( len = :), allocatable :: path !> Namespace which the dependency belongs to. !> Enables multiple dependencies with the same name. !> Required for dependencies that are obtained via the official registry. character ( len = :), allocatable :: namespace !> The requested version of the dependency. !> The latest version is used if not specified. type ( version_t ), allocatable :: requested_version !> Requested macros for the dependency type ( preprocess_config_t ), allocatable :: preprocess (:) !> Git descriptor type ( git_target_t ), allocatable :: git contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => dependency_is_same procedure :: dump_to_toml procedure :: load_from_toml end type dependency_config_t !> Common output format for writing to the command line character ( len =* ), parameter :: out_fmt = '(\"#\", *(1x, g0))' interface resize module procedure resize_dependency_config end interface resize contains !> Construct a new dependency configuration from a TOML data structure subroutine new_dependency ( self , table , root , error ) !> Instance of the dependency configuration type ( dependency_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( * ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: uri , value , requested_version type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call table % get_key ( self % name ) call get_value ( table , \"namespace\" , self % namespace ) call get_value ( table , \"v\" , requested_version ) if ( allocated ( requested_version )) then if (. not . allocated ( self % requested_version )) allocate ( self % requested_version ) call new_version ( self % requested_version , requested_version , error ) if ( allocated ( error )) return end if !> Get optional preprocessor directives call get_value ( table , \"preprocess\" , child , requested = . false .) if ( associated ( child )) then call new_preprocessors ( self % preprocess , child , error ) if ( allocated ( error )) return endif call get_value ( table , \"path\" , uri ) if ( allocated ( uri )) then if ( get_os_type () == OS_WINDOWS ) uri = windows_path ( uri ) if ( present ( root )) uri = join_path ( root , uri ) ! Relative to the fpm.toml it’s written in call move_alloc ( uri , self % path ) return end if call get_value ( table , \"git\" , uri ) if ( allocated ( uri )) then call get_value ( table , \"tag\" , value ) if ( allocated ( value )) then self % git = git_target_tag ( uri , value ) end if if (. not . allocated ( self % git )) then call get_value ( table , \"branch\" , value ) if ( allocated ( value )) then self % git = git_target_branch ( uri , value ) end if end if if (. not . allocated ( self % git )) then call get_value ( table , \"rev\" , value ) if ( allocated ( value )) then self % git = git_target_revision ( uri , value ) end if end if if (. not . allocated ( self % git )) then self % git = git_target_default ( uri ) end if return end if end subroutine new_dependency !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: name type ( toml_key ), allocatable :: list (:) type ( toml_table ), pointer :: child !> List of valid keys for the dependency table. character ( * ), dimension ( * ), parameter :: valid_keys = [ character ( 24 ) :: & & \"namespace\" , & \"v\" , & \"path\" , & \"git\" , & \"tag\" , & \"branch\" , & \"rev\" , & \"preprocess\" & & ] call table % get_key ( name ) call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Dependency '\" // name // \"' does not provide sufficient entries\" ) return end if call check_keys ( table , valid_keys , error ) if ( allocated ( error )) return if ( table % has_key ( \"path\" ) . and . table % has_key ( \"git\" )) then call syntax_error ( error , \"Dependency '\" // name // \"' cannot have both git and path entries\" ) return end if if (( table % has_key ( \"branch\" ) . and . table % has_key ( \"rev\" )) . or . & ( table % has_key ( \"branch\" ) . and . table % has_key ( \"tag\" )) . or . & ( table % has_key ( \"rev\" ) . and . table % has_key ( \"tag\" ))) then call syntax_error ( error , \"Dependency '\" // name // \"' can only have one of branch, rev or tag present\" ) return end if if (( table % has_key ( \"branch\" ) . or . table % has_key ( \"tag\" ) . or . table % has_key ( \"rev\" )) & . and . . not . table % has_key ( \"git\" )) then call syntax_error ( error , \"Dependency '\" // name // \"' has git identifier but no git url\" ) return end if if (. not . table % has_key ( \"path\" ) . and . . not . table % has_key ( \"git\" ) & . and . . not . table % has_key ( \"namespace\" )) then call syntax_error ( error , \"Please provide a 'namespace' for dependency '\" // name // & & \"' if it is not a local path or git repository\" ) return end if if ( table % has_key ( 'v' ) . and . ( table % has_key ( 'path' ) . or . table % has_key ( 'git' ))) then call syntax_error ( error , \"Dependency '\" // name // \"' cannot have both v and git/path entries\" ) return end if ! Check preprocess key if ( table % has_key ( 'preprocess' )) then call get_value ( table , 'preprocess' , child ) if (. not . associated ( child )) then call syntax_error ( error , \"Dependency '\" // name // \"' has invalid 'preprocess' entry\" ) return end if end if end subroutine check !> Construct new dependency array from a TOML data structure subroutine new_dependencies ( deps , table , root , meta , error ) !> Instance of the dependency configuration type ( dependency_config_t ), allocatable , intent ( out ) :: deps (:) !> (optional) metapackages type ( metapackage_config_t ), optional , intent ( out ) :: meta !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( * ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: node type ( toml_key ), allocatable :: list (:) type ( dependency_config_t ), allocatable :: all_deps (:) type ( metapackage_request_t ) :: meta_request logical , allocatable :: is_meta (:) logical :: metapackages_allowed integer :: idep , stat , ndep call table % get_keys ( list ) ! An empty table is okay if ( size ( list ) < 1 ) return !> Flag dependencies that should be treated as metapackages metapackages_allowed = present ( meta ) allocate ( is_meta ( size ( list )), source = . false .) allocate ( all_deps ( size ( list ))) !> Parse all meta- and non-metapackage dependencies do idep = 1 , size ( list ) ! Check if this is a standard dependency node call get_value ( table , list ( idep )% key , node , stat = stat ) is_standard_dependency : if ( stat /= toml_stat % success ) then ! See if it can be a valid metapackage name call new_meta_request ( meta_request , list ( idep )% key , table , error = error ) !> Neither a standard dep nor a metapackage if ( allocated ( error )) then call syntax_error ( error , \"Dependency \" // list ( idep )% key // \" is not a valid metapackage or a table entry\" ) return endif !> Valid meta dependency is_meta ( idep ) = . true . else ! Parse as a standard dependency is_meta ( idep ) = . false . call new_dependency ( all_deps ( idep ), node , root , error ) if ( allocated ( error )) return end if is_standard_dependency end do ! Non-meta dependencies ndep = count (. not . is_meta ) ! Finalize standard dependencies allocate ( deps ( ndep )) ndep = 0 do idep = 1 , size ( list ) if ( is_meta ( idep )) cycle ndep = ndep + 1 deps ( ndep ) = all_deps ( idep ) end do ! Finalize meta dependencies if ( metapackages_allowed ) call new_meta_config ( meta , table , is_meta , error ) end subroutine new_dependencies !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the dependency configuration class ( dependency_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if write ( unit , fmt ) \"Dependency\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % git )) then write ( unit , fmt ) \"- kind\" , \"git\" call self % git % info ( unit , pr - 1 ) end if if ( allocated ( self % path )) then write ( unit , fmt ) \"- kind\" , \"local\" write ( unit , fmt ) \"- path\" , self % path end if end subroutine info !> Check if two dependency configurations are different logical function manifest_has_changed ( cached , manifest , verbosity , iunit ) result ( has_changed ) !> Two instances of the dependency configuration class ( dependency_config_t ), intent ( in ) :: cached , manifest !> Log verbosity integer , intent ( in ) :: verbosity , iunit has_changed = . true . !> Perform all checks if ( allocated ( cached % git ). neqv . allocated ( manifest % git )) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT presence has changed. \" return endif if ( allocated ( cached % git )) then if (. not . git_matches_manifest ( cached % git , manifest % git , verbosity , iunit )) return end if !> All checks passed! The two instances are equal has_changed = . false . end function manifest_has_changed !> Clean memory elemental subroutine dependency_destroy ( self ) class ( dependency_config_t ), intent ( inout ) :: self if ( allocated ( self % name )) deallocate ( self % name ) if ( allocated ( self % path )) deallocate ( self % path ) if ( allocated ( self % namespace )) deallocate ( self % namespace ) if ( allocated ( self % requested_version )) deallocate ( self % requested_version ) if ( allocated ( self % git )) deallocate ( self % git ) end subroutine dependency_destroy !> Check that two dependency configs are equal logical function dependency_is_same ( this , that ) class ( dependency_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that dependency_is_same = . false . select type ( other => that ) type is ( dependency_config_t ) if (. not .( this % name == other % name )) return if (. not .( this % path == other % path )) return if (. not .( this % namespace == other % namespace )) return if (. not .( allocated ( this % requested_version ). eqv . allocated ( other % requested_version ))) return if ( allocated ( this % requested_version )) then if (. not .( this % requested_version == other % requested_version )) return endif if (. not .( allocated ( this % git ). eqv . allocated ( other % git ))) return if ( allocated ( this % git )) then if (. not .( this % git == other % git )) return endif class default ! Not the same type return end select !> All checks passed! dependency_is_same = . true . end function dependency_is_same !> Dump dependency to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( toml_table ), pointer :: ptr type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_string ( table , \"name\" , self % name , error , 'dependency_config_t' ) if ( allocated ( error )) return call set_string ( table , \"path\" , self % path , error , 'dependency_config_t' ) if ( allocated ( error )) return call set_string ( table , \"namespace\" , self % namespace , error , 'dependency_config_t' ) if ( allocated ( error )) return if ( allocated ( self % requested_version )) then call set_string ( table , \"requested_version\" , self % requested_version % s (), error , 'dependency_config_t' ) if ( allocated ( error )) return endif if ( allocated ( self % git )) then call add_table ( table , \"git\" , ptr , error ) if ( allocated ( error )) return call self % git % dump_to_toml ( ptr , error ) if ( allocated ( error )) return endif end subroutine dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables type ( toml_key ), allocatable :: list (:) type ( toml_table ), pointer :: ptr character ( len = :), allocatable :: requested_version integer :: ierr , ii call dependency_destroy ( self ) call get_value ( table , \"name\" , self % name ) call get_value ( table , \"path\" , self % path ) call get_value ( table , \"namespace\" , self % namespace ) call get_value ( table , \"requested_version\" , requested_version ) if ( allocated ( requested_version )) then allocate ( self % requested_version ) call new_version ( self % requested_version , requested_version , error ) if ( allocated ( error )) then error % message = 'dependency_config_t: version error from TOML table - ' // error % message return endif end if call table % get_keys ( list ) add_git : do ii = 1 , size ( list ) if ( list ( ii )% key == \"git\" ) then call get_value ( table , list ( ii )% key , ptr , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'dependency_config_t: cannot retrieve git from TOML table' ) exit endif allocate ( self % git ) call self % git % load_from_toml ( ptr , error ) if ( allocated ( error )) return exit add_git end if end do add_git end subroutine load_from_toml !> Reallocate a list of dependencies pure subroutine resize_dependency_config ( var , n ) !> Instance of the array to be resized type ( dependency_config_t ), allocatable , intent ( inout ) :: var (:) !> Dimension of the final array size integer , intent ( in ), optional :: n type ( dependency_config_t ), allocatable :: tmp (:) integer :: this_size , new_size integer , parameter :: initial_size = 16 if ( allocated ( var )) then this_size = size ( var , 1 ) call move_alloc ( var , tmp ) else this_size = initial_size end if if ( present ( n )) then new_size = n else new_size = this_size + this_size / 2 + 1 end if allocate ( var ( new_size )) if ( allocated ( tmp )) then this_size = min ( size ( tmp , 1 ), size ( var , 1 )) var (: this_size ) = tmp (: this_size ) deallocate ( tmp ) end if end subroutine resize_dependency_config end module fpm_manifest_dependency","tags":"","loc":"sourcefile/dependency.f90.html"},{"title":"fpm_filesystem.F90 – Fortran-lang/fpm","text":"Source Code !> This module contains general routines for interacting with the file system !! module fpm_filesystem use , intrinsic :: iso_fortran_env , only : stdin => input_unit , stdout => output_unit , stderr => error_unit use , intrinsic :: iso_c_binding , only : c_new_line use fpm_environment , only : get_os_type , & OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_WINDOWS , & OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD use fpm_environment , only : separator , get_env , os_is_unix use fpm_strings , only : f_string , replace , string_t , split , split_first_last , dilate , str_begins_with_str use iso_c_binding , only : c_char , c_ptr , c_int , c_null_char , c_associated , c_f_pointer use fpm_error , only : fpm_stop , error_t , fatal_error implicit none private public :: basename , canon_path , dirname , is_dir , join_path , number_of_rows , list_files , get_local_prefix , & mkdir , exists , get_temp_filename , windows_path , unix_path , getline , delete_file , fileopen , fileclose , & filewrite , warnwrite , parent_dir , is_hidden_file , read_lines , read_lines_expanded , which , run , & os_delete_dir , is_absolute_path , get_home , execute_and_read_output , get_dos_path #ifndef FPM_BOOTSTRAP interface function c_opendir ( dir ) result ( r ) bind ( c , name = \"c_opendir\" ) import c_char , c_ptr character ( kind = c_char ), intent ( in ) :: dir ( * ) type ( c_ptr ) :: r end function c_opendir function c_readdir ( dir ) result ( r ) bind ( c , name = \"c_readdir\" ) import c_ptr type ( c_ptr ), intent ( in ), value :: dir type ( c_ptr ) :: r end function c_readdir function c_closedir ( dir ) result ( r ) bind ( c , name = \"closedir\" ) import c_ptr , c_int type ( c_ptr ), intent ( in ), value :: dir integer ( kind = c_int ) :: r end function c_closedir function c_get_d_name ( dir ) result ( r ) bind ( c , name = \"get_d_name\" ) import c_ptr type ( c_ptr ), intent ( in ), value :: dir type ( c_ptr ) :: r end function c_get_d_name function c_is_dir ( path ) result ( r ) bind ( c , name = \"c_is_dir\" ) import c_char , c_int character ( kind = c_char ), intent ( in ) :: path ( * ) integer ( kind = c_int ) :: r end function c_is_dir end interface #endif character ( * ), parameter :: eol = new_line ( 'a' ) !! End of line contains !> Extract filename from path with/without suffix function basename ( path , suffix ) result ( base ) character ( * ), intent ( In ) :: path logical , intent ( in ), optional :: suffix character (:), allocatable :: base character (:), allocatable :: file_parts (:) logical :: with_suffix if (. not . present ( suffix )) then with_suffix = . true . else with_suffix = suffix end if call split ( path , file_parts , delimiters = '\\/' ) if ( size ( file_parts ) > 0 ) then base = trim ( file_parts ( size ( file_parts ))) else base = '' endif if (. not . with_suffix ) then call split ( base , file_parts , delimiters = '.' ) if ( size ( file_parts ) >= 2 ) then base = trim ( file_parts ( size ( file_parts ) - 1 )) endif endif end function basename !> Canonicalize path for comparison !! * Handles path string redundancies !! * Does not test existence of path !! !! To be replaced by realpath/_fullname in stdlib_os !! !! FIXME: Lot's of ugly hacks following here function canon_path ( path ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: canon_path character ( len = :), allocatable :: nixpath integer :: istart , iend , nn , last logical :: is_path , absolute nixpath = unix_path ( path ) istart = 0 nn = 0 iend = 0 absolute = nixpath ( 1 : 1 ) == \"/\" if ( absolute ) then canon_path = \"/\" else canon_path = \"\" end if do while ( iend < len ( nixpath )) call next ( nixpath , istart , iend , is_path ) if ( is_path ) then select case ( nixpath ( istart : iend )) case ( \".\" , \"\" ) ! always drop empty paths case ( \"..\" ) if ( nn > 0 ) then last = scan ( canon_path (: len ( canon_path ) - 1 ), \"/\" , back = . true .) canon_path = canon_path (: last ) nn = nn - 1 else if (. not . absolute ) then canon_path = canon_path // nixpath ( istart : iend ) // \"/\" end if end if case default nn = nn + 1 canon_path = canon_path // nixpath ( istart : iend ) // \"/\" end select end if end do if ( len ( canon_path ) == 0 ) canon_path = \".\" if ( len ( canon_path ) > 1 . and . canon_path ( len ( canon_path ):) == \"/\" ) then canon_path = canon_path (: len ( canon_path ) - 1 ) end if contains subroutine next ( string , istart , iend , is_path ) character ( len =* ), intent ( in ) :: string integer , intent ( inout ) :: istart integer , intent ( inout ) :: iend logical , intent ( inout ) :: is_path integer :: ii , nn character :: tok nn = len ( string ) if ( iend >= nn ) then istart = nn iend = nn return end if ii = min ( iend + 1 , nn ) tok = string ( ii : ii ) is_path = tok /= '/' if (. not . is_path ) then is_path = . false . istart = ii iend = ii return end if istart = ii do ii = min ( iend + 1 , nn ), nn tok = string ( ii : ii ) select case ( tok ) case ( '/' ) exit case default iend = ii cycle end select end do end subroutine next end function canon_path !> Extract dirname from path function dirname ( path ) result ( dir ) character ( * ), intent ( in ) :: path character (:), allocatable :: dir dir = path ( 1 : scan ( path , '/\\',back=.true.)) end function dirname !> Extract dirname from path function parent_dir(path) result (dir) character(*), intent(in) :: path character(:), allocatable :: dir dir = path(1:scan(path,' / \\ ',back=.true.)-1) end function parent_dir !> test if a name matches an existing directory path logical function is_dir(dir) character(*), intent(in) :: dir integer :: stat select case (get_os_type()) case (OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD) call run( \"test -d \" // dir , & & exitstat=stat,echo=.false.,verbose=.false.) case (OS_WINDOWS) call run(' cmd / c \"if not exist ' // windows_path(dir) // '\\ exit /B 1\" ', & & exitstat=stat,echo=.false.,verbose=.false.) end select is_dir = (stat == 0) end function is_dir !> test if a file is hidden logical function is_hidden_file(file_basename) result(r) character(*), intent(in) :: file_basename if (len(file_basename) <= 2) then r = .false. else r = str_begins_with_str(file_basename, ' . ') end if end function is_hidden_file !> Construct path by joining strings with os file separator function join_path(a1,a2,a3,a4,a5) result(path) character(len=*), intent(in) :: a1, a2 character(len=*), intent(in), optional :: a3, a4, a5 character(len=:), allocatable :: path character(len=1) :: filesep logical, save :: has_cache = .false. character(len=1), save :: cache = ' / ' !$omp threadprivate(has_cache, cache) if (has_cache) then filesep = cache else select case (get_os_type()) case default filesep = ' / ' case (OS_WINDOWS) filesep = ' \\ ' end select cache = filesep has_cache = .true. end if if (a1 == \"\") then path = a2 else path = a1 // filesep // a2 end if if (present(a3)) then path = path // filesep // a3 else return end if if (present(a4)) then path = path // filesep // a4 else return end if if (present(a5)) then path = path // filesep // a5 else return end if end function join_path !> Determine number or rows in a file given a LUN integer function number_of_rows(s) result(nrows) integer,intent(in)::s integer :: ios rewind(s) nrows = 0 do read(s, *, iostat=ios) if (ios /= 0) exit nrows = nrows + 1 end do rewind(s) end function number_of_rows !> read lines into an array of TYPE(STRING_T) variables expanding tabs function read_lines_expanded(filename) result(lines) character(len=*), intent(in) :: filename type(string_t), allocatable :: lines(:) integer :: i character(len=:), allocatable :: content integer, allocatable :: first(:), last(:) content = read_text_file(filename) if (len(content) == 0) then allocate (lines(0)) return end if call split_first_last(content, eol, first, last) ! TODO: \\r (< macOS X), \\n (>=macOS X/Linux/Unix), \\r\\n (Windows) ! allocate lines from file content string allocate (lines(size(first))) do i = 1, size(first) allocate(lines(i)%s, source=dilate(content(first(i):last(i)))) end do end function read_lines_expanded !> read lines into an array of TYPE(STRING_T) variables function read_lines(filename) result(lines) character(len=*), intent(in) :: filename type(string_t), allocatable :: lines(:) integer :: i character(len=:), allocatable :: content integer, allocatable :: first(:), last(:) content = read_text_file(filename) if (len(content) == 0) then allocate (lines(0)) return end if call split_first_last(content, eol, first, last) ! TODO: \\r (< macOS X), \\n (>=macOS X/Linux/Unix), \\r\\n (Windows) ! allocate lines from file content string allocate (lines(size(first))) do i = 1, size(first) allocate(lines(i)%s, source=content(first(i):last(i))) end do end function read_lines !> read text file into a string function read_text_file(filename) result(string) character(len=*), intent(in) :: filename character(len=:), allocatable :: string integer :: fh, length open (newunit=fh, file=filename, status=' old ', action=' read ', & access=' stream ', form=' unformatted ') inquire (fh, size=length) allocate (character(len=length) :: string) if (length == 0) return read (fh) string close (fh) end function read_text_file !> Create a directory. Create subdirectories as needed subroutine mkdir(dir, echo) character(len=*), intent(in) :: dir logical, intent(in), optional :: echo integer :: stat if (is_dir(dir)) return select case (get_os_type()) case (OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD) call run(' mkdir - p ' // dir, exitstat=stat,echo=echo,verbose=.false.) case (OS_WINDOWS) call run(\"mkdir \" // windows_path(dir), & & echo=echo, exitstat=stat,verbose=.false.) end select if (stat /= 0) then call fpm_stop(1, ' * mkdir * : directory creation failed ') end if end subroutine mkdir #ifndef FPM_BOOTSTRAP !> Get file & directory names in directory `dir` using iso_c_binding. !! !! - File/directory names return are relative to cwd, ie. preprended with `dir` !! - Includes files starting with `.` except current directory and parent directory !! recursive subroutine list_files(dir, files, recurse) character(len=*), intent(in) :: dir type(string_t), allocatable, intent(out) :: files(:) logical, intent(in), optional :: recurse integer :: i type(string_t), allocatable :: dir_files(:) type(string_t), allocatable :: sub_dir_files(:) type(c_ptr) :: dir_handle type(c_ptr) :: dir_entry_c character(len=:,kind=c_char), allocatable :: fortran_name character(len=:), allocatable :: string_fortran integer, parameter :: N_MAX = 256 type(string_t) :: files_tmp(N_MAX) integer(kind=c_int) :: r if (c_is_dir(dir(1:len_trim(dir))//c_null_char) == 0) then allocate (files(0)) return end if dir_handle = c_opendir(dir(1:len_trim(dir))//c_null_char) if (.not. c_associated(dir_handle)) then print *, ' c_opendir () failed ' error stop end if i = 0 allocate(files(0)) do dir_entry_c = c_readdir(dir_handle) if (.not. c_associated(dir_entry_c)) then exit else string_fortran = f_string(c_get_d_name(dir_entry_c)) if ((string_fortran == ' . ' .or. string_fortran == ' .. ')) then cycle end if i = i + 1 if (i > N_MAX) then files = [files, files_tmp] i = 1 end if files_tmp(i)%s = join_path(dir, string_fortran) end if end do r = c_closedir(dir_handle) if (r /= 0) then print *, ' c_closedir () failed ' error stop end if if (i > 0) then files = [files, files_tmp(1:i)] end if if (present(recurse)) then if (recurse) then allocate(sub_dir_files(0)) do i=1,size(files) if (c_is_dir(files(i)%s//c_null_char) /= 0) then call list_files(files(i)%s, dir_files, recurse=.true.) sub_dir_files = [sub_dir_files, dir_files] end if end do files = [files, sub_dir_files] end if end if end subroutine list_files #else !> Get file & directory names in directory `dir`. !! !! - File/directory names return are relative to cwd, ie. preprended with `dir` !! - Includes files starting with `.` except current directory and parent directory !! recursive subroutine list_files(dir, files, recurse) character(len=*), intent(in) :: dir type(string_t), allocatable, intent(out) :: files(:) logical, intent(in), optional :: recurse integer :: stat, fh, i character(:), allocatable :: temp_file type(string_t), allocatable :: dir_files(:) type(string_t), allocatable :: sub_dir_files(:) if (.not. is_dir(dir)) then allocate (files(0)) return end if allocate (temp_file, source=get_temp_filename()) select case (get_os_type()) case (OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD) call run(' ls - A ' // dir , & & redirect=temp_file, exitstat=stat,echo=.false.,verbose=.false.) case (OS_WINDOWS) call run(' dir / b ' // windows_path(dir), & & redirect=temp_file, exitstat=stat,echo=.false.,verbose=.false.) end select if (stat /= 0) then call fpm_stop(2,' * list_files * : directory listing failed ') end if files = read_lines(temp_file) call delete_file(temp_file) do i=1,size(files) files(i)%s = join_path(dir,files(i)%s) end do if (present(recurse)) then if (recurse) then allocate(sub_dir_files(0)) do i=1,size(files) if (is_dir(files(i)%s)) then call list_files(files(i)%s, dir_files, recurse=.true.) sub_dir_files = [sub_dir_files, dir_files] end if end do files = [files, sub_dir_files] end if end if end subroutine list_files #endif !> test if pathname already exists logical function exists(filename) result(r) character(len=*), intent(in) :: filename inquire(file=filename, exist=r) !> Directories are not files for the Intel compilers. If so, also use this compiler-dependent extension #if defined(__INTEL_COMPILER) if (.not.r) inquire(directory=filename, exist=r) #endif end function !> Get a unused temporary filename !! Calls posix ' tempnam ' - not recommended, but !! we have no security concerns for this application !! and use here is temporary. !! Works with MinGW function get_temp_filename() result(tempfile) ! use iso_c_binding, only: c_ptr, C_NULL_PTR, c_f_pointer integer, parameter :: MAX_FILENAME_LENGTH = 32768 character(:), allocatable :: tempfile type(c_ptr) :: c_tempfile_ptr character(len=1), pointer :: c_tempfile(:) interface function c_tempnam(dir,pfx) result(tmp) bind(c,name=\"tempnam\") import type(c_ptr), intent(in), value :: dir type(c_ptr), intent(in), value :: pfx type(c_ptr) :: tmp end function c_tempnam subroutine c_free(ptr) BIND(C,name=\"free\") import type(c_ptr), value :: ptr end subroutine c_free end interface c_tempfile_ptr = c_tempnam(C_NULL_PTR, C_NULL_PTR) call c_f_pointer(c_tempfile_ptr,c_tempfile,[MAX_FILENAME_LENGTH]) tempfile = f_string(c_tempfile) call c_free(c_tempfile_ptr) end function get_temp_filename !> Replace file system separators for windows function windows_path(path) result(winpath) character(*), intent(in) :: path character(:), allocatable :: winpath integer :: idx winpath = path idx = index(winpath,' / ') do while(idx > 0) winpath(idx:idx) = ' \\ ' idx = index(winpath,' / ') end do end function windows_path !> Replace file system separators for unix function unix_path(path) result(nixpath) character(*), intent(in) :: path character(:), allocatable :: nixpath integer :: idx nixpath = path idx = index(nixpath,' \\ ') do while(idx > 0) nixpath(idx:idx) = ' / ' idx = index(nixpath,' \\ ') end do end function unix_path !>AUTHOR: fpm(1) contributors !!LICENSE: MIT !> !!##NAME !! getline(3f) - [M_io:READ] read a line of arbintrary length from specified !! LUN into allocatable string (up to system line length limit) !! (LICENSE:PD) !! !!##SYNTAX !! subroutine getline(unit,line,iostat,iomsg) !! !! integer,intent(in) :: unit !! character(len=:),allocatable,intent(out) :: line !! integer,intent(out) :: iostat !! character(len=:), allocatable, optional :: iomsg !! !!##DESCRIPTION !! Read a line of any length up to programming environment maximum !! line length. Requires Fortran 2003+. !! !! It is primarily expected to be used when reading input which will !! then be parsed or echoed. !! !! The input file must have a PAD attribute of YES for the function !! to work properly, which is typically true. !! !! The simple use of a loop that repeatedly re-allocates a character !! variable in addition to reading the input file one buffer at a !! time could (depending on the programming environment used) be !! inefficient, as it could reallocate and allocate memory used for !! the output string with each buffer read. !! !!##OPTIONS !! LINE The line read when IOSTAT returns as zero. !! LUN LUN (Fortran logical I/O unit) number of file open and ready !! to read. !! IOSTAT status returned by READ(IOSTAT=IOS). If not zero, an error !! occurred or an end-of-file or end-of-record was encountered. !! IOMSG error message returned by system when IOSTAT is not zero. !! !!##EXAMPLE !! !! Sample program: !! !! program demo_getline !! use,intrinsic :: iso_fortran_env, only : stdin=>input_unit !! use,intrinsic :: iso_fortran_env, only : iostat_end !! use FPM_filesystem, only : getline !! implicit none !! integer :: iostat !! character(len=:),allocatable :: line, iomsg !! open(unit=stdin,pad=' yes ') !! INFINITE: do !! call getline(stdin,line,iostat,iomsg) !! if(iostat /= 0) exit INFINITE !! write(*,' ( a ) ')' [ '//line//' ] ' !! enddo INFINITE !! if(iostat /= iostat_end)then !! write(*,*)' error reading input : ',iomsg !! endif !! end program demo_getline !! subroutine getline(unit, line, iostat, iomsg) !> Formatted IO unit integer, intent(in) :: unit !> Line to read character(len=:), allocatable, intent(out) :: line !> Status of operation integer, intent(out) :: iostat !> Error message character(len=:), allocatable, optional :: iomsg integer, parameter :: BUFFER_SIZE = 1024 character(len=BUFFER_SIZE) :: buffer character(len=256) :: msg integer :: size integer :: stat allocate(character(len=0) :: line) do read(unit, ' ( a ) ', advance=' no ', iostat=stat, iomsg=msg, size=size) & & buffer if (stat > 0) exit line = line // buffer(:size) if (stat < 0) then if (is_iostat_eor(stat)) then stat = 0 end if exit end if end do if (stat /= 0) then if (present(iomsg)) iomsg = trim(msg) end if iostat = stat end subroutine getline !> delete a file by filename subroutine delete_file(file) character(len=*), intent(in) :: file logical :: exist integer :: unit inquire(file=file, exist=exist) if (exist) then open(file=file, newunit=unit) close(unit, status=\"delete\") end if end subroutine delete_file !> write trimmed character data to a file if it does not exist subroutine warnwrite(fname,data) character(len=*),intent(in) :: fname character(len=*),intent(in) :: data(:) if(.not.exists(fname))then call filewrite(fname,data) else write(stderr,' ( * ( g0 , 1 x )) ')' < INFO > ',fname,& & ' already exists . Not overwriting ' endif end subroutine warnwrite !> procedure to open filename as a sequential \"text\" file subroutine fileopen(filename,lun,ier) character(len=*),intent(in) :: filename integer,intent(out) :: lun integer,intent(out),optional :: ier integer :: ios character(len=256) :: message message=' ' ios=0 if(filename/=' ')then open(file=filename, & & newunit=lun, & & form=' formatted ', & ! FORM = FORMATTED | UNFORMATTED & access=' sequential ', & ! ACCESS = SEQUENTIAL| DIRECT | STREAM & action=' write ', & ! ACTION = READ|WRITE| READWRITE & position=' rewind ', & ! POSITION= ASIS | REWIND | APPEND & status=' new ', & ! STATUS = NEW| REPLACE| OLD| SCRATCH| UNKNOWN & iostat=ios, & & iomsg=message) else lun=stdout ios=0 endif if(ios/=0)then lun=-1 if(present(ier))then ier=ios else call fpm_stop(3,' * fileopen * : '//filename//' : '//trim(message)) endif endif end subroutine fileopen !> simple close of a LUN. On error show message and stop (by default) subroutine fileclose(lun,ier) integer,intent(in) :: lun integer,intent(out),optional :: ier character(len=256) :: message integer :: ios if(lun/=-1)then close(unit=lun,iostat=ios,iomsg=message) if(ios/=0)then if(present(ier))then ier=ios else call fpm_stop(4,' * fileclose * : '//trim(message)) endif endif endif end subroutine fileclose !> procedure to write filedata to file filename subroutine filewrite(filename,filedata) character(len=*),intent(in) :: filename character(len=*),intent(in) :: filedata(:) integer :: lun, i, ios character(len=256) :: message call fileopen(filename,lun) if(lun/=-1)then ! program currently stops on error on open, but might ! want it to continue so -1 (unallowed LUN) indicates error ! write file do i=1,size(filedata) write(lun,' ( a ) ',iostat=ios,iomsg=message)trim(filedata(i)) if(ios/=0)then call fpm_stop(5,' * filewrite * : '//filename//' : '//trim(message)) endif enddo endif ! close file call fileclose(lun) end subroutine filewrite !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!##Name !! which(3f) - [M_io:ENVIRONMENT] given a command name find the pathname by searching !! the directories in the environment variable $PATH !! (LICENSE:PD) !! !!##Syntax !! function which(command) result(pathname) !! !! character(len=*),intent(in) :: command !! character(len=:),allocatable :: pathname !! !!##Description !! Given a command name find the first file with that name in the directories !! specified by the environment variable $PATH. !! !!##options !! COMMAND the command to search for !! !!##Returns !! PATHNAME the first pathname found in the current user path. Returns blank !! if the command is not found. !! !!##Example !! !! Sample program: !! !! Checking the error message and counting lines: !! !! program demo_which !! use M_io, only : which !! implicit none !! write(*,*)' ls is ',which(' ls ') !! write(*,*)' dir is ',which(' dir ') !! write(*,*)' install is ',which(' install ') !! end program demo_which !! function which(command) result(pathname) character(len=*),intent(in) :: command character(len=:),allocatable :: pathname, checkon, paths(:), exts(:) integer :: i, j pathname='' call split(get_env(' PATH '),paths,delimiters=merge(' ; ',' : ',separator()==' \\ ')) SEARCH: do i=1,size(paths) checkon=trim(join_path(trim(paths(i)),command)) select case(separator()) case(' / ') if(exists(checkon))then pathname=checkon exit SEARCH endif case(' \\ ') if(exists(checkon))then pathname=checkon exit SEARCH endif if(exists(checkon//' . bat '))then pathname=checkon//' . bat ' exit SEARCH endif if(exists(checkon//' . exe '))then pathname=checkon//' . exe ' exit SEARCH endif call split(get_env(' PATHEXT '),exts,delimiters=' ; ') do j=1,size(exts) if(exists(checkon//' . '//trim(exts(j))))then pathname=checkon//' . '//trim(exts(j)) exit SEARCH endif enddo end select enddo SEARCH end function which !>AUTHOR: fpm(1) contributors !!LICENSE: MIT !> !!##Name !! run(3f) - execute specified system command and selectively echo !! command and output to a file and/or stdout. !! (LICENSE:MIT) !! !!##Syntax !! subroutine run(cmd,echo,exitstat,verbose,redirect) !! !! character(len=*), intent(in) :: cmd !! logical,intent(in),optional :: echo !! integer, intent(out),optional :: exitstat !! logical, intent(in), optional :: verbose !! character(*), intent(in), optional :: redirect !! !!##Description !! Execute the specified system command. Optionally !! !! + echo the command before execution !! + return the system exit status of the command. !! + redirect the output of the command to a file. !! + echo command output to stdout !! !! Calling run(3f) is preferred to direct calls to !! execute_command_line(3f) in the fpm(1) source to provide a standard !! interface where output modes can be specified. !! !!##Options !! CMD System command to execute !! ECHO Whether to echo the command being executed or not !! Defaults to .TRUE. . !! VERBOSE Whether to redirect the command output to a null device or not !! Defaults to .TRUE. . !! REDIRECT Filename to redirect stdout and stderr of the command into. !! If generated it is closed before run(3f) returns. !! EXITSTAT The system exit status of the command when supported by !! the system. If not present and a non-zero status is !! generated program termination occurs. !! !!##Example !! !! Sample program: !! !! Checking the error message and counting lines: !! !! program demo_run !! use fpm_filesystem, only : run !! implicit none !! logical,parameter :: T=.true., F=.false. !! integer :: exitstat !! character(len=:),allocatable :: cmd !! cmd=' ls - ltrasd * . md ' !! call run(cmd) !! call run(cmd,exitstat=exitstat) !! call run(cmd,echo=F) !! call run(cmd,verbose=F) !! end program demo_run !! subroutine run(cmd,echo,exitstat,verbose,redirect) character(len=*), intent(in) :: cmd logical,intent(in),optional :: echo integer, intent(out),optional :: exitstat logical, intent(in), optional :: verbose character(*), intent(in), optional :: redirect integer :: cmdstat character(len=256) :: cmdmsg, iomsg logical :: echo_local, verbose_local character(:), allocatable :: redirect_str character(:), allocatable :: line integer :: stat, fh, iostat if(present(echo))then echo_local=echo else echo_local=.true. end if if(present(verbose))then verbose_local=verbose else verbose_local=.true. end if if (present(redirect)) then if(redirect /= '')then redirect_str = \">\"//redirect//\" 2>&1\" else redirect_str = \"\" endif else if(verbose_local)then ! No redirection but verbose output redirect_str = \"\" else ! No redirection and non-verbose output if (os_is_unix()) then redirect_str = \" >/dev/null 2>&1\" else redirect_str = \" >NUL 2>&1\" end if end if end if if(echo_local) print *, ' + ', cmd !//redirect_str call execute_command_line(cmd//redirect_str, exitstat=stat,cmdstat=cmdstat,cmdmsg=cmdmsg) if(cmdstat /= 0)then write(*,' ( a ) ')' < ERROR > : failed command '//cmd//redirect_str call fpm_stop(1,' * run * : '//trim(cmdmsg)) endif if (verbose_local.and.present(redirect)) then open(newunit=fh,file=redirect,status=' old ',iostat=iostat,iomsg=iomsg) if(iostat == 0)then do call getline(fh, line, iostat) if (iostat /= 0) exit write(*,' ( A ) ') trim(line) end do else write(*,' ( A ) ') trim(iomsg) endif close(fh) end if if (present(exitstat)) then exitstat = stat elseif (stat /= 0) then call fpm_stop(stat,' * run * : Command '//cmd//redirect_str//' returned a non - zero status code ') end if end subroutine run !> Delete directory using system OS remove directory commands subroutine os_delete_dir(is_unix, dir, echo) logical, intent(in) :: is_unix character(len=*), intent(in) :: dir logical, intent(in), optional :: echo if (is_unix) then call run(' rm - rf ' // dir, echo=echo,verbose=.false.) else call run(' rmdir / s / q ' // dir, echo=echo,verbose=.false.) end if end subroutine os_delete_dir !> Determine the path prefix to the local folder. Used for installation, registry etc. function get_local_prefix(os) result(prefix) !> Installation prefix character(len=:), allocatable :: prefix !> Platform identifier integer, intent(in), optional :: os !> Default installation prefix on Unix platforms character(len=*), parameter :: default_prefix_unix = \"/usr/local\" !> Default installation prefix on Windows platforms character(len=*), parameter :: default_prefix_win = \"C:\\\" character(len=:), allocatable :: home if (os_is_unix(os)) then home=get_env(' HOME ','') if (home /= '' ) then prefix = join_path(home, \".local\") else prefix = default_prefix_unix end if else home=get_env(' APPDATA ','') if (home /= '' ) then prefix = join_path(home, \"local\") else prefix = default_prefix_win end if end if end function get_local_prefix !> Returns .true. if provided path is absolute. !> !> `~` not treated as absolute. logical function is_absolute_path(path, is_unix) character(len=*), intent(in) :: path logical, optional, intent(in):: is_unix character(len=*), parameter :: letters = ' ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' logical :: is_unix_os if (present(is_unix)) then is_unix_os = is_unix else is_unix_os = os_is_unix() end if if (is_unix_os) then is_absolute_path = path(1:1) == ' / ' else if (len(path) < 2) then is_absolute_path = .false. return end if is_absolute_path = index(letters, path(1:1)) /= 0 .and. path(2:2) == ' : ' end if end function is_absolute_path !> Get the HOME directory on Unix and the %USERPROFILE% directory on Windows. subroutine get_home(home, error) character(len=:), allocatable, intent(out) :: home type(error_t), allocatable, intent(out) :: error if (os_is_unix()) then home=get_env(' HOME ','') if ( home == '' ) then call fatal_error(error, \"Couldn' t retrieve 'HOME' variable \") return end if else home=get_env('USERPROFILE','') if ( home == '' ) then call fatal_error(error, \" Couldn 't retrieve ' % USERPROFILE % ' variable\") return end if end if end subroutine get_home !> Execute command line and return output as a string. subroutine execute_and_read_output(cmd, output, error, verbose) !> Command to execute. character(len=*), intent(in) :: cmd !> Command line output. character(len=:), allocatable, intent(out) :: output !> Error to handle. type(error_t), allocatable, intent(out) :: error !> Print additional information if true. logical, intent(in), optional :: verbose integer :: exitstat, unit, stat character(len=:), allocatable :: cmdmsg, tmp_file, output_line logical :: is_verbose if (present(verbose)) then is_verbose = verbose else is_verbose = .false. end if tmp_file = get_temp_filename() call run(cmd//' > '//tmp_file, exitstat=exitstat, echo=is_verbose) if (exitstat /= 0) call fatal_error(error, ' * run * : '//\"Command failed: ' \"//cmd//\" '. Message: ' \"//trim(cmdmsg)//\" '.\") open(newunit=unit, file=tmp_file, action=' read ', status=' old ') output = '' do call getline(unit, output_line, stat) if (stat /= 0) exit output = output//output_line//' ' end do if (is_verbose) print *, output close(unit, status=' delete ') end !> Ensure a windows path is converted to an 8.3 DOS path if it contains spaces function get_dos_path(path,error) character(len=*), intent(in) :: path type(error_t), allocatable, intent(out) :: error character(len=:), allocatable :: get_dos_path character(:), allocatable :: redirect,screen_output,line integer :: stat,cmdstat,iunit,last ! Non-Windows OS if (get_os_type()/=OS_WINDOWS) then get_dos_path = path return end if ! Trim path first get_dos_path = trim(path) !> No need to convert if there are no spaces has_spaces: if (scan(get_dos_path,' ')>0) then redirect = get_temp_filename() call execute_command_line(' cmd / c for % A in ( \"'//path//'\" ) do @ echo % ~ sA > '//redirect//' 2 > & 1 ',& exitstat=stat,cmdstat=cmdstat) !> Read screen output command_OK: if (cmdstat==0 .and. stat==0) then allocate(character(len=0) :: screen_output) open(newunit=iunit,file=redirect,status=' old ',iostat=stat) if (stat == 0)then do call getline(iunit, line, stat) if (stat /= 0) exit screen_output = screen_output//line//' ' end do ! Close and delete file close(iunit,status=' delete ') else call fatal_error(error,' cannot read temporary file from successful DOS path evaluation ') return endif else command_OK call fatal_error(error,' unsuccessful Windows -> DOS path command ') return end if command_OK get_dos_path = trim(adjustl(screen_output)) endif has_spaces !> Ensure there are no trailing slashes last = len_trim(get_dos_path) if (last>1 .and. get_dos_path(last:last)==' / ' .or. get_dos_path(last:last)==' \\' ) get_dos_path = get_dos_path ( 1 : last - 1 ) end function get_dos_path end module fpm_filesystem","tags":"","loc":"sourcefile/fpm_filesystem.f90.html"},{"title":"downloader.f90 – Fortran-lang/fpm","text":"Source Code module fpm_downloader use fpm_error , only : error_t , fatal_error use fpm_filesystem , only : which , run use fpm_versioning , only : version_t use jonquil , only : json_object , json_value , json_error , json_load , cast_to_object use fpm_strings , only : string_t implicit none private public :: downloader_t !> This type could be entirely avoided but it is quite practical because it can be mocked for testing. type downloader_t contains procedure , nopass :: get_pkg_data , get_file , upload_form , unpack end type contains !> Perform an http get request, save output to file, and parse json. subroutine get_pkg_data ( url , version , tmp_pkg_file , json , error ) character ( * ), intent ( in ) :: url type ( version_t ), allocatable , intent ( in ) :: version character ( * ), intent ( in ) :: tmp_pkg_file type ( json_object ), intent ( out ) :: json type ( error_t ), allocatable , intent ( out ) :: error class ( json_value ), allocatable :: j_value type ( json_object ), pointer :: ptr type ( json_error ), allocatable :: j_error if ( allocated ( version )) then ! Request specific version. call get_file ( url // '/' // version % s (), tmp_pkg_file , error ) else ! Request latest version. call get_file ( url , tmp_pkg_file , error ) end if if ( allocated ( error )) return call json_load ( j_value , tmp_pkg_file , error = j_error ) if ( allocated ( j_error )) then allocate ( error ); call move_alloc ( j_error % message , error % message ); call json % destroy (); return end if ptr => cast_to_object ( j_value ) if (. not . associated ( ptr )) then call fatal_error ( error , \"Error parsing JSON from '\" // url // \"'.\" ); return end if json = ptr end !> Download a file from a url using either curl or wget. subroutine get_file ( url , tmp_pkg_file , error ) character ( * ), intent ( in ) :: url character ( * ), intent ( in ) :: tmp_pkg_file type ( error_t ), allocatable , intent ( out ) :: error integer :: stat if ( which ( 'curl' ) /= '' ) then print * , \"Downloading '\" // url // \"' -> '\" // tmp_pkg_file // \"'\" call execute_command_line ( 'curl ' // url // ' -s -o ' // tmp_pkg_file , exitstat = stat ) else if ( which ( 'wget' ) /= '' ) then print * , \"Downloading '\" // url // \"' -> '\" // tmp_pkg_file // \"'\" call execute_command_line ( 'wget ' // url // ' -q -O ' // tmp_pkg_file , exitstat = stat ) else call fatal_error ( error , \"Neither 'curl' nor 'wget' installed.\" ); return end if if ( stat /= 0 ) then call fatal_error ( error , \"Error downloading package from '\" // url // \"'.\" ); return end if end !> Perform an http post request with form data. subroutine upload_form ( endpoint , form_data , verbose , error ) !> Endpoint to upload to. character ( len =* ), intent ( in ) :: endpoint !> Form data to upload. type ( string_t ), intent ( in ) :: form_data (:) !> Print additional information if true. logical , intent ( in ) :: verbose !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , i character ( len = :), allocatable :: form_data_str form_data_str = '' do i = 1 , size ( form_data ) form_data_str = form_data_str // \"-F '\" // form_data ( i )% s // \"' \" end do if ( which ( 'curl' ) /= '' ) then print * , 'Uploading package ...' call run ( 'curl -X POST -H \"Content-Type: multipart/form-data\" ' // & & form_data_str // endpoint , exitstat = stat , echo = verbose ) else call fatal_error ( error , \"'curl' not installed.\" ); return end if if ( stat /= 0 ) then call fatal_error ( error , \"Error uploading package to registry.\" ); return end if end !> Unpack a tarball to a destination. subroutine unpack ( tmp_pkg_file , destination , error ) !> Path to tarball. character ( * ), intent ( in ) :: tmp_pkg_file !> Destination to unpack to. character ( * ), intent ( in ) :: destination !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error integer :: stat if ( which ( 'tar' ) == '' ) then call fatal_error ( error , \"'tar' not installed.\" ); return end if print * , \"Unpacking '\" // tmp_pkg_file // \"' to '\" // destination // \"' ...\" call execute_command_line ( 'tar -zxf ' // tmp_pkg_file // ' -C ' // destination , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error unpacking '\" // tmp_pkg_file // \"'.\" ); return end if end end","tags":"","loc":"sourcefile/downloader.f90.html"},{"title":"fpm_os.F90 – Fortran-lang/fpm","text":"Source Code module fpm_os use , intrinsic :: iso_c_binding , only : c_char , c_int , c_null_char , c_ptr , c_associated use fpm_filesystem , only : exists , join_path , get_home use fpm_environment , only : os_is_unix use fpm_error , only : error_t , fatal_error implicit none private public :: change_directory , get_current_directory , get_absolute_path , convert_to_absolute_path , & & get_absolute_path_by_cd integer ( c_int ), parameter :: buffersize = 1000_c_int #ifndef _WIN32 character ( len =* ), parameter :: pwd_env = \"PWD\" #else character ( len =* ), parameter :: pwd_env = \"CD\" #endif interface function chdir_ ( path ) result ( stat ) & #ifndef _WIN32 bind ( C , name = \"chdir\" ) #else bind ( C , name = \"_chdir\" ) #endif import :: c_char , c_int character ( kind = c_char , len = 1 ), intent ( in ) :: path ( * ) integer ( c_int ) :: stat end function chdir_ function getcwd_ ( buf , bufsize ) result ( path ) & #ifndef _WIN32 bind ( C , name = \"getcwd\" ) #else bind ( C , name = \"_getcwd\" ) #endif import :: c_char , c_int , c_ptr character ( kind = c_char , len = 1 ), intent ( in ) :: buf ( * ) integer ( c_int ), value , intent ( in ) :: bufsize type ( c_ptr ) :: path end function getcwd_ !> Determine the absolute, canonicalized path for a given path. Unix-only. function realpath ( path , resolved_path ) result ( ptr ) bind ( C ) import :: c_ptr , c_char , c_int character ( kind = c_char , len = 1 ), intent ( in ) :: path ( * ) character ( kind = c_char , len = 1 ), intent ( out ) :: resolved_path ( * ) type ( c_ptr ) :: ptr end function realpath !> Determine the absolute, canonicalized path for a given path. Windows-only. function fullpath ( resolved_path , path , maxLength ) result ( ptr ) bind ( C , name = \"_fullpath\" ) import :: c_ptr , c_char , c_int character ( kind = c_char , len = 1 ), intent ( in ) :: path ( * ) character ( kind = c_char , len = 1 ), intent ( out ) :: resolved_path ( * ) integer ( c_int ), value , intent ( in ) :: maxLength type ( c_ptr ) :: ptr end function fullpath !> Determine the absolute, canonicalized path for a given path. !> Calls custom C routine because the `_WIN32` macro is correctly exported !> in C using `gfortran`. function c_realpath ( path , resolved_path , maxLength ) result ( ptr ) & bind ( C , name = \"c_realpath\" ) import :: c_ptr , c_char , c_int character ( kind = c_char , len = 1 ), intent ( in ) :: path ( * ) character ( kind = c_char , len = 1 ), intent ( out ) :: resolved_path ( * ) integer ( c_int ), value , intent ( in ) :: maxLength type ( c_ptr ) :: ptr end function c_realpath end interface contains subroutine change_directory ( path , error ) character ( len =* ), intent ( in ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: cpath (:) integer :: stat allocate ( cpath ( len ( path ) + 1 )) call f_c_character ( path , cpath , len ( path ) + 1 ) stat = chdir_ ( cpath ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to change directory to '\" // path // \"'\" ) end if end subroutine change_directory subroutine get_current_directory ( path , error ) character ( len = :), allocatable , intent ( out ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: cpath (:) type ( c_ptr ) :: tmp allocate ( cpath ( buffersize )) tmp = getcwd_ ( cpath , buffersize ) if ( c_associated ( tmp )) then call c_f_character ( cpath , path ) else call fatal_error ( error , \"Failed to retrieve current directory\" ) end if end subroutine get_current_directory subroutine f_c_character ( rhs , lhs , len ) character ( kind = c_char ), intent ( out ) :: lhs ( * ) character ( len =* ), intent ( in ) :: rhs integer , intent ( in ) :: len integer :: length length = min ( len - 1 , len_trim ( rhs )) lhs ( 1 : length ) = transfer ( rhs ( 1 : length ), lhs ( 1 : length )) lhs ( length + 1 : length + 1 ) = c_null_char end subroutine f_c_character subroutine c_f_character ( rhs , lhs ) character ( kind = c_char ), intent ( in ) :: rhs ( * ) character ( len = :), allocatable , intent ( out ) :: lhs integer :: ii do ii = 1 , huge ( ii ) - 1 if ( rhs ( ii ) == c_null_char ) then exit end if end do allocate ( character ( len = ii - 1 ) :: lhs ) lhs = transfer ( rhs ( 1 : ii - 1 ), lhs ) end subroutine c_f_character !> Determine the canonical, absolute path for the given path. !> !> Calls a C routine that uses the `_WIN32` macro to determine the correct function. !> !> Cannot be used in bootstrap mode. subroutine get_realpath ( path , real_path , error ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable , intent ( out ) :: real_path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: appended_path (:) character ( kind = c_char , len = 1 ), allocatable :: cpath (:) type ( c_ptr ) :: ptr if (. not . exists ( path )) then call fatal_error ( error , \"Cannot determine absolute path. Path '\" // path // \"' does not exist.\" ) return end if allocate ( appended_path ( len ( path ) + 1 )) call f_c_character ( path , appended_path , len ( path ) + 1 ) allocate ( cpath ( buffersize )) #ifndef FPM_BOOTSTRAP ptr = c_realpath ( appended_path , cpath , buffersize ) #endif if ( c_associated ( ptr )) then call c_f_character ( cpath , real_path ) else call fatal_error ( error , \"Failed to retrieve absolute path for '\" // path // \"'.\" ) end if end subroutine !> Determine the canonical, absolute path for the given path. !> Expands home folder (~) on both Unix and Windows. subroutine get_absolute_path ( path , absolute_path , error ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable , intent ( out ) :: absolute_path type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: home #ifdef FPM_BOOTSTRAP call get_absolute_path_by_cd ( path , absolute_path , error ); return #endif if ( len_trim ( path ) < 1 ) then call fatal_error ( error , 'Path cannot be empty' ); return else if ( path ( 1 : 1 ) == '~' ) then call get_home ( home , error ) if ( allocated ( error )) return if ( len_trim ( path ) == 1 ) then absolute_path = home ; return end if if ( os_is_unix ()) then if ( path ( 2 : 2 ) /= '/' ) then call fatal_error ( error , \"Wrong separator in path: '\" // path // \"'\" ); return end if else if ( path ( 2 : 2 ) /= '\\') then call fatal_error(error, \"Wrong separator in path: ' \"//path//\" '\"); return end if end if if (len_trim(path) == 2) then absolute_path = home; return end if absolute_path = join_path(home, path(3:len_trim(path))) if (.not. exists(absolute_path)) then call fatal_error(error, \"Path not found: ' \"//absolute_path//\" '\" ); return end if else ! Get canonicalized absolute path from either the absolute or the relative path. call get_realpath ( path , absolute_path , error ) end if end subroutine !> Alternative to `get_absolute_path` that uses `chdir`/`_chdir` to determine the absolute path. !> !> `get_absolute_path` is preferred but `get_absolute_path_by_cd` can be used in bootstrap mode. subroutine get_absolute_path_by_cd ( path , absolute_path , error ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable , intent ( out ) :: absolute_path type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: current_path call get_current_directory ( current_path , error ) if ( allocated ( error )) return call change_directory ( path , error ) if ( allocated ( error )) return call get_current_directory ( absolute_path , error ) if ( allocated ( error )) return call change_directory ( current_path , error ) if ( allocated ( error )) return end subroutine !> Converts a path to an absolute, canonical path. subroutine convert_to_absolute_path ( path , error ) character ( len = :), allocatable , intent ( inout ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: absolute_path call get_absolute_path ( path , absolute_path , error ) path = absolute_path end subroutine end module fpm_os","tags":"","loc":"sourcefile/fpm_os.f90.html"},{"title":"dependency.f90 – Fortran-lang/fpm","text":"Source Code !> # Dependency management !> !> ## Fetching dependencies and creating a dependency tree !> !> Dependencies on the top-level can be specified from: !> !> - `package%dependencies` !> - `package%dev_dependencies` !> - `package%executable(:)%dependencies` !> - `package%test(:)%dependencies` !> !> Each dependency is fetched in some way and provides a path to its package !> manifest. !> The `package%dependencies` of the dependencies are resolved recursively. !> !> To initialize the dependency tree all dependencies are recursively fetched !> and stored in a flat data structure to avoid retrieving a package twice. !> The data structure used to store this information should describe the current !> status of the dependency tree. Important information are: !> !> - name of the package !> - version of the package !> - path to the package root !> !> Additionally, for version controlled dependencies the following should be !> stored along with the package: !> !> - the upstream url !> - the current checked out revision !> !> Fetching a remote (version controlled) dependency turns it for our purpose !> into a local path dependency which is handled by the same means. !> !> ## Updating dependencies !> !> For a given dependency tree all top-level dependencies can be updated. !> We have two cases to consider, a remote dependency and a local dependency, !> again, remote dependencies turn into local dependencies by fetching. !> Therefore we will update remote dependencies by simply refetching them. !> !> For remote dependencies we have to refetch if the revision in the manifest !> changes or the upstream HEAD has changed (for branches _and_ tags). !> !> @Note For our purpose a tag is just a fancy branch name. Tags can be delete and !> modified afterwards, therefore they do not differ too much from branches !> from our perspective. !> !> For the latter case we only know if we actually fetch from the upstream URL. !> !> In case of local (and fetched remote) dependencies we have to read the package !> manifest and compare its dependencies against our dependency tree, any change !> requires updating the respective dependencies as well. !> !> ## Handling dependency compatibilties !> !> Currenly ignored. First come, first serve. module fpm_dependency use , intrinsic :: iso_fortran_env , only : output_unit use fpm_environment , only : get_os_type , OS_WINDOWS , os_is_unix use fpm_error , only : error_t , fatal_error use fpm_filesystem , only : exists , join_path , mkdir , canon_path , windows_path , list_files , is_dir , basename , & os_delete_dir , get_temp_filename use fpm_git , only : git_target_revision , git_target_default , git_revision , serializable_t use fpm_manifest , only : package_config_t , dependency_config_t , get_package_data use fpm_manifest_dependency , only : manifest_has_changed , dependency_destroy use fpm_manifest_preprocess , only : operator ( == ) use fpm_strings , only : string_t , operator (. in .) use fpm_toml , only : toml_table , toml_key , toml_error , toml_serialize , & get_value , set_value , add_table , toml_load , toml_stat , set_string use fpm_versioning , only : version_t , new_version use fpm_settings , only : fpm_global_settings , get_global_settings , official_registry_base_url use fpm_downloader , only : downloader_t use jonquil , only : json_object use fpm_strings , only : str implicit none private public :: dependency_tree_t , new_dependency_tree , dependency_node_t , new_dependency_node , resize , & & check_and_read_pkg_data , destroy_dependency_node !> Overloaded reallocation interface interface resize module procedure :: resize_dependency_node end interface resize !> Dependency node in the projects dependency tree type , extends ( dependency_config_t ) :: dependency_node_t !> Actual version of this dependency type ( version_t ), allocatable :: version !> Installation prefix of this dependencies character ( len = :), allocatable :: proj_dir !> Checked out revision of the version control system character ( len = :), allocatable :: revision !> Dependency is handled logical :: done = . false . !> Dependency should be updated logical :: update = . false . !> Dependency was loaded from a cache logical :: cached = . false . contains !> Update dependency from project manifest. procedure :: register !> Get dependency from the registry. procedure :: get_from_registry procedure , private :: get_from_local_registry !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => dependency_node_is_same procedure :: dump_to_toml => node_dump_to_toml procedure :: load_from_toml => node_load_from_toml end type dependency_node_t !> Respresentation of a projects dependencies !> !> The dependencies are stored in a simple array for now, this can be replaced !> with a binary-search tree or a hash table in the future. type , extends ( serializable_t ) :: dependency_tree_t !> Unit for IO integer :: unit = output_unit !> Verbosity of printout integer :: verbosity = 1 !> Installation prefix for dependencies character ( len = :), allocatable :: dep_dir !> Number of currently registered dependencies integer :: ndep = 0 !> Flattend list of all dependencies type ( dependency_node_t ), allocatable :: dep (:) !> Cache file character ( len = :), allocatable :: cache contains !> Overload procedure to add new dependencies to the tree generic :: add => add_project , add_project_dependencies , add_dependencies , & add_dependency , add_dependency_node !> Main entry point to add a project procedure , private :: add_project !> Add a project and its dependencies to the dependency tree procedure , private :: add_project_dependencies !> Add a list of dependencies to the dependency tree procedure , private :: add_dependencies !> Add a single dependency to the dependency tree procedure , private :: add_dependency !> Add a single dependency node to the dependency tree procedure , private :: add_dependency_node !> Resolve dependencies generic :: resolve => resolve_dependencies , resolve_dependency !> Resolve dependencies procedure , private :: resolve_dependencies !> Resolve dependency procedure , private :: resolve_dependency !> True if entity can be found generic :: has => has_dependency !> True if dependency is part of the tree procedure , private :: has_dependency !> Find a dependency in the tree generic :: find => find_name !> Find a dependency by its name procedure , private :: find_name !> Depedendncy resolution finished procedure :: finished !> Reading of dependency tree generic :: load_cache => load_cache_from_file , load_cache_from_unit , load_cache_from_toml !> Read dependency tree from file procedure , private :: load_cache_from_file !> Read dependency tree from formatted unit procedure , private :: load_cache_from_unit !> Read dependency tree from TOML data structure procedure , private :: load_cache_from_toml !> Writing of dependency tree generic :: dump_cache => dump_cache_to_file , dump_cache_to_unit , dump_cache_to_toml !> Write dependency tree to file procedure , private :: dump_cache_to_file !> Write dependency tree to formatted unit procedure , private :: dump_cache_to_unit !> Write dependency tree to TOML data structure procedure , private :: dump_cache_to_toml !> Update dependency tree generic :: update => update_dependency , update_tree !> Update a list of dependencies procedure , private :: update_dependency !> Update all dependencies in the tree procedure , private :: update_tree !> Serialization interface procedure :: serializable_is_same => dependency_tree_is_same procedure :: dump_to_toml => tree_dump_to_toml procedure :: load_from_toml => tree_load_from_toml end type dependency_tree_t !> Common output format for writing to the command line character ( len =* ), parameter :: out_fmt = '(\"#\", *(1x, g0))' contains !> Create a new dependency tree subroutine new_dependency_tree ( self , verbosity , cache ) !> Instance of the dependency tree type ( dependency_tree_t ), intent ( out ) :: self !> Verbosity of printout integer , intent ( in ), optional :: verbosity !> Name of the cache file character ( len =* ), intent ( in ), optional :: cache call resize ( self % dep ) self % dep_dir = join_path ( \"build\" , \"dependencies\" ) if ( present ( verbosity )) self % verbosity = verbosity if ( present ( cache )) self % cache = cache end subroutine new_dependency_tree !> Create a new dependency node from a configuration subroutine new_dependency_node ( self , dependency , version , proj_dir , update ) !> Instance of the dependency node type ( dependency_node_t ), intent ( out ) :: self !> Dependency configuration data type ( dependency_config_t ), intent ( in ) :: dependency !> Version of the dependency type ( version_t ), intent ( in ), optional :: version !> Installation prefix of the dependency character ( len =* ), intent ( in ), optional :: proj_dir !> Dependency should be updated logical , intent ( in ), optional :: update self % dependency_config_t = dependency if ( present ( version )) then self % version = version end if if ( present ( proj_dir )) then self % proj_dir = proj_dir end if if ( present ( update )) then self % update = update end if end subroutine new_dependency_node !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the dependency configuration class ( dependency_node_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if !> Call base object info call self % dependency_config_t % info ( unit , pr ) if ( allocated ( self % version )) then write ( unit , fmt ) \"- version\" , self % version % s () end if if ( allocated ( self % proj_dir )) then write ( unit , fmt ) \"- dir\" , self % proj_dir end if if ( allocated ( self % revision )) then write ( unit , fmt ) \"- revision\" , self % revision end if write ( unit , fmt ) \"- done\" , merge ( 'YES' , 'NO ' , self % done ) write ( unit , fmt ) \"- update\" , merge ( 'YES' , 'NO ' , self % update ) end subroutine info !> Add project dependencies, each depth level after each other. !> !> We implement this algorithm in an interative rather than a recursive fashion !> as a choice of design. subroutine add_project ( self , package , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Project configuration to add type ( package_config_t ), intent ( in ) :: package !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( dependency_config_t ) :: dependency type ( dependency_tree_t ) :: cached character ( len =* ), parameter :: root = '.' integer :: id if (. not . exists ( self % dep_dir )) then call mkdir ( self % dep_dir ) end if ! Create this project as the first dependency node (depth 0) dependency % name = package % name dependency % path = root call self % add ( dependency , error ) if ( allocated ( error )) return ! Resolve the root project call self % resolve ( root , error ) if ( allocated ( error )) return ! Add the root project dependencies (depth 1) call self % add ( package , root , . true ., error ) if ( allocated ( error )) return ! After resolving all dependencies, check if we have cached ones to avoid updates if ( allocated ( self % cache )) then call new_dependency_tree ( cached , verbosity = self % verbosity , cache = self % cache ) call cached % load_cache ( self % cache , error ) if ( allocated ( error )) return ! Skip root node do id = 2 , cached % ndep cached % dep ( id )% cached = . true . call self % add ( cached % dep ( id ), error ) if ( allocated ( error )) return end do end if ! Now decent into the dependency tree, level for level do while (. not . self % finished ()) call self % resolve ( root , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return if ( allocated ( self % cache )) then call self % dump_cache ( self % cache , error ) if ( allocated ( error )) return end if end subroutine add_project !> Add a project and its dependencies to the dependency tree recursive subroutine add_project_dependencies ( self , package , root , main , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Project configuration to add type ( package_config_t ), intent ( in ) :: package !> Current project root directory character ( len =* ), intent ( in ) :: root !> Is the main project logical , intent ( in ) :: main !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ii if ( allocated ( package % dependency )) then call self % add ( package % dependency , error ) if ( allocated ( error )) return end if if ( main ) then if ( allocated ( package % dev_dependency )) then call self % add ( package % dev_dependency , error ) if ( allocated ( error )) return end if if ( allocated ( package % executable )) then do ii = 1 , size ( package % executable ) if ( allocated ( package % executable ( ii )% dependency )) then call self % add ( package % executable ( ii )% dependency , error ) if ( allocated ( error )) exit end if end do if ( allocated ( error )) return end if if ( allocated ( package % example )) then do ii = 1 , size ( package % example ) if ( allocated ( package % example ( ii )% dependency )) then call self % add ( package % example ( ii )% dependency , error ) if ( allocated ( error )) exit end if end do if ( allocated ( error )) return end if if ( allocated ( package % test )) then do ii = 1 , size ( package % test ) if ( allocated ( package % test ( ii )% dependency )) then call self % add ( package % test ( ii )% dependency , error ) if ( allocated ( error )) exit end if end do if ( allocated ( error )) return end if end if !> Ensure allocation fits call resize ( self % dep , self % ndep ) end subroutine add_project_dependencies !> Add a list of dependencies to the dependency tree subroutine add_dependencies ( self , dependency , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Dependency configuration to add type ( dependency_config_t ), intent ( in ) :: dependency (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ii , ndep ndep = size ( self % dep ) if ( ndep < size ( dependency ) + self % ndep ) then call resize ( self % dep , ndep + ndep / 2 + size ( dependency )) end if do ii = 1 , size ( dependency ) call self % add ( dependency ( ii ), error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return !> Ensure allocation fits ndep call resize ( self % dep , self % ndep ) end subroutine add_dependencies !> Add a single dependency node to the dependency tree !> Dependency nodes contain additional information (version, git, revision) subroutine add_dependency_node ( self , dependency , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Dependency configuration to add type ( dependency_node_t ), intent ( in ) :: dependency !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: id if ( self % has_dependency ( dependency )) then ! A dependency with this same name is already in the dependency tree. ! Check if it needs to be updated id = self % find ( dependency % name ) ! If this dependency was in the cache, and we're now requesting a different version ! in the manifest, ensure it is marked for update. Otherwise, if we're just querying ! the same dependency from a lower branch of the dependency tree, the existing one from ! the manifest has priority if ( dependency % cached ) then if ( dependency_has_changed ( dependency , self % dep ( id ), self % verbosity , self % unit )) then if ( self % verbosity > 0 ) write ( self % unit , out_fmt ) \"Dependency change detected:\" , dependency % name self % dep ( id )% update = . true . else ! Store the cached one self % dep ( id ) = dependency self % dep ( id )% update = . false . end if end if else !> Safety: reallocate if necessary if ( size ( self % dep ) == self % ndep ) call resize ( self % dep , self % ndep + 1 ) ! New dependency: add from scratch self % ndep = self % ndep + 1 self % dep ( self % ndep ) = dependency self % dep ( self % ndep )% update = . false . end if end subroutine add_dependency_node !> Add a single dependency to the dependency tree subroutine add_dependency ( self , dependency , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Dependency configuration to add type ( dependency_config_t ), intent ( in ) :: dependency !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( dependency_node_t ) :: node call new_dependency_node ( node , dependency ) call add_dependency_node ( self , node , error ) end subroutine add_dependency !> Update dependency tree subroutine update_dependency ( self , name , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Name of the dependency to update character ( len =* ), intent ( in ) :: name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: id character ( len = :), allocatable :: proj_dir , root id = self % find ( name ) root = \".\" if ( id <= 0 ) then call fatal_error ( error , \"Cannot update dependency '\" // name // \"'\" ) return end if associate ( dep => self % dep ( id )) if ( allocated ( dep % git ) . and . dep % update ) then if ( self % verbosity > 0 ) write ( self % unit , out_fmt ) \"Update:\" , dep % name proj_dir = join_path ( self % dep_dir , dep % name ) call dep % git % checkout ( proj_dir , error ) if ( allocated ( error )) return ! Unset dependency and remove updatable attribute dep % done = . false . dep % update = . false . ! Now decent into the dependency tree, level for level do while (. not . self % finished ()) call self % resolve ( root , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return end if end associate end subroutine update_dependency !> Update whole dependency tree subroutine update_tree ( self , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i ! Update dependencies where needed do i = 1 , self % ndep call self % update ( self % dep ( i )% name , error ) if ( allocated ( error )) return end do end subroutine update_tree !> Resolve all dependencies in the tree subroutine resolve_dependencies ( self , root , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Current installation prefix character ( len =* ), intent ( in ) :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( fpm_global_settings ) :: global_settings integer :: ii call get_global_settings ( global_settings , error ) if ( allocated ( error )) return do ii = 1 , self % ndep call self % resolve ( self % dep ( ii ), global_settings , root , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return end subroutine resolve_dependencies !> Resolve a single dependency node subroutine resolve_dependency ( self , dependency , global_settings , root , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Dependency configuration to add type ( dependency_node_t ), intent ( inout ) :: dependency !> Global configuration settings. type ( fpm_global_settings ), intent ( in ) :: global_settings !> Current installation prefix character ( len =* ), intent ( in ) :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( package_config_t ) :: package character ( len = :), allocatable :: manifest , proj_dir , revision logical :: fetch if ( dependency % done ) return fetch = . false . if ( allocated ( dependency % proj_dir )) then proj_dir = dependency % proj_dir else if ( allocated ( dependency % path )) then proj_dir = join_path ( root , dependency % path ) else if ( allocated ( dependency % git )) then proj_dir = join_path ( self % dep_dir , dependency % name ) fetch = . not . exists ( proj_dir ) if ( fetch ) then call dependency % git % checkout ( proj_dir , error ) if ( allocated ( error )) return end if else call dependency % get_from_registry ( proj_dir , global_settings , error ) if ( allocated ( error )) return end if if ( allocated ( dependency % git )) then call git_revision ( proj_dir , revision , error ) if ( allocated ( error )) return end if manifest = join_path ( proj_dir , \"fpm.toml\" ) call get_package_data ( package , manifest , error ) if ( allocated ( error )) return call dependency % register ( package , proj_dir , fetch , revision , error ) if ( allocated ( error )) return if ( self % verbosity > 1 ) then write ( self % unit , out_fmt ) & \"Dep:\" , dependency % name , \"version\" , dependency % version % s (), & \"at\" , dependency % proj_dir end if call self % add ( package , proj_dir , . false ., error ) if ( allocated ( error )) return end subroutine resolve_dependency !> Get a dependency from the registry. Whether the dependency is fetched !> from a local, a custom remote or the official registry is determined !> by the global configuration settings. subroutine get_from_registry ( self , target_dir , global_settings , error , downloader_ ) !> Instance of the dependency configuration. class ( dependency_node_t ), intent ( in ) :: self !> The target directory of the dependency. character (:), allocatable , intent ( out ) :: target_dir !> Global configuration settings. type ( fpm_global_settings ), intent ( in ) :: global_settings !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error !> Downloader instance. class ( downloader_t ), optional , intent ( in ) :: downloader_ character (:), allocatable :: cache_path , target_url , tmp_file type ( version_t ) :: version integer :: stat , unit type ( json_object ) :: json class ( downloader_t ), allocatable :: downloader if ( present ( downloader_ )) then downloader = downloader_ else allocate ( downloader ) end if ! Use local registry if it was specified in the global config file. if ( allocated ( global_settings % registry_settings % path )) then call self % get_from_local_registry ( target_dir , global_settings % registry_settings % path , error ); return end if ! Include namespace and package name in the cache path. cache_path = join_path ( global_settings % registry_settings % cache_path , self % namespace , self % name ) ! Check cache before downloading from the remote registry if a specific version was requested. When no specific ! version was requested, do network request first to check which is the newest version. if ( allocated ( self % requested_version )) then if ( exists ( join_path ( cache_path , self % requested_version % s (), 'fpm.toml' ))) then print * , \"Using cached version of '\" , join_path ( self % namespace , self % name , self % requested_version % s ()), \"'.\" target_dir = join_path ( cache_path , self % requested_version % s ()); return end if end if tmp_file = get_temp_filename () open ( newunit = unit , file = tmp_file , action = 'readwrite' , iostat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error creating temporary file for downloading package '\" // self % name // \"'.\" ); return end if ! Include namespace and package name in the target url and download package data. target_url = global_settings % registry_settings % url // 'packages/' // self % namespace // '/' // self % name call downloader % get_pkg_data ( target_url , self % requested_version , tmp_file , json , error ) close ( unit , status = 'delete' ) if ( allocated ( error )) return ! Verify package data and read relevant information. call check_and_read_pkg_data ( json , self , target_url , version , error ) if ( allocated ( error )) return ! Open new tmp file for downloading the actual package. open ( newunit = unit , file = tmp_file , action = 'readwrite' , iostat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error creating temporary file for downloading package '\" // self % name // \"'.\" ); return end if ! Include version number in the cache path. If no cached version exists, download it. cache_path = join_path ( cache_path , version % s ()) if (. not . exists ( join_path ( cache_path , 'fpm.toml' ))) then if ( is_dir ( cache_path )) call os_delete_dir ( os_is_unix (), cache_path ) call mkdir ( cache_path ) call downloader % get_file ( target_url , tmp_file , error ) if ( allocated ( error )) then close ( unit , status = 'delete' ); return end if ! Unpack the downloaded package to the final location. call downloader % unpack ( tmp_file , cache_path , error ) close ( unit , status = 'delete' ) if ( allocated ( error )) return end if target_dir = cache_path end subroutine get_from_registry subroutine check_and_read_pkg_data ( json , node , download_url , version , error ) type ( json_object ), intent ( inout ) :: json class ( dependency_node_t ), intent ( in ) :: node character (:), allocatable , intent ( out ) :: download_url type ( version_t ), intent ( out ) :: version type ( error_t ), allocatable , intent ( out ) :: error integer :: code , stat type ( json_object ), pointer :: p , q character (:), allocatable :: version_key , version_str , error_message , namespace , name namespace = \"\" name = \"UNNAMED_NODE\" if ( allocated ( node % namespace )) namespace = node % namespace if ( allocated ( node % name )) name = node % name if (. not . json % has_key ( 'code' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No status code.\" ); return end if call get_value ( json , 'code' , code , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': \" // & & \"Failed to read status code.\" ); return end if if ( code /= 200 ) then if (. not . json % has_key ( 'message' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No error message.\" ); return end if call get_value ( json , 'message' , error_message , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': \" // & & \"Failed to read error message.\" ); return end if call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"'. Status code: '\" // & & str ( code ) // \"'. Error message: '\" // error_message // \"'.\" ); return end if if (. not . json % has_key ( 'data' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No data.\" ); return end if call get_value ( json , 'data' , p , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to read package data for '\" // join_path ( namespace , name ) // \"'.\" ); return end if if ( allocated ( node % requested_version )) then version_key = 'version_data' else version_key = 'latest_version_data' end if if (. not . p % has_key ( version_key )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No version data.\" ); return end if call get_value ( p , version_key , q , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to retrieve version data for '\" // join_path ( namespace , name ) // \"'.\" ); return end if if (. not . q % has_key ( 'download_url' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No download url.\" ); return end if call get_value ( q , 'download_url' , download_url , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to read download url for '\" // join_path ( namespace , name ) // \"'.\" ); return end if download_url = official_registry_base_url // download_url if (. not . q % has_key ( 'version' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No version found.\" ); return end if call get_value ( q , 'version' , version_str , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to read version data for '\" // join_path ( namespace , name ) // \"'.\" ); return end if call new_version ( version , version_str , error ) if ( allocated ( error )) then call fatal_error ( error , \"'\" // version_str // \"' is not a valid version for '\" // & & join_path ( namespace , name ) // \"'.\" ); return end if end subroutine !> Get the dependency from a local registry. subroutine get_from_local_registry ( self , target_dir , registry_path , error ) !> Instance of the dependency configuration. class ( dependency_node_t ), intent ( in ) :: self !> The target directory to download the dependency to. character (:), allocatable , intent ( out ) :: target_dir !> The path to the local registry. character ( * ), intent ( in ) :: registry_path !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error character (:), allocatable :: path_to_name type ( string_t ), allocatable :: files (:) type ( version_t ), allocatable :: versions (:) type ( version_t ) :: version integer :: i path_to_name = join_path ( registry_path , self % namespace , self % name ) if (. not . exists ( path_to_name )) then call fatal_error ( error , \"Dependency resolution of '\" // self % name // & & \"': Directory '\" // path_to_name // \"' doesn't exist.\" ); return end if call list_files ( path_to_name , files ) if ( size ( files ) == 0 ) then call fatal_error ( error , \"No versions of '\" // self % name // \"' found in '\" // path_to_name // \"'.\" ); return end if ! Version requested, find it in the cache. if ( allocated ( self % requested_version )) then do i = 1 , size ( files ) ! Identify directory that matches the version number. if ( files ( i )% s == join_path ( path_to_name , self % requested_version % s ()) . and . is_dir ( files ( i )% s )) then if (. not . exists ( join_path ( files ( i )% s , 'fpm.toml' ))) then call fatal_error ( error , \"'\" // files ( i )% s // \"' is missing an 'fpm.toml' file.\" ); return end if target_dir = files ( i )% s ; return end if end do call fatal_error ( error , \"Version '\" // self % requested_version % s () // \"' not found in '\" // path_to_name // \"'\" ) return end if ! No specific version requested, therefore collect available versions. allocate ( versions ( 0 )) do i = 1 , size ( files ) if ( is_dir ( files ( i )% s )) then call new_version ( version , basename ( files ( i )% s ), error ) if ( allocated ( error )) return versions = [ versions , version ] end if end do if ( size ( versions ) == 0 ) then call fatal_error ( error , \"No versions found in '\" // path_to_name // \"'\" ); return end if ! Find the latest version. version = versions ( 1 ) do i = 1 , size ( versions ) if ( versions ( i ) > version ) version = versions ( i ) end do path_to_name = join_path ( path_to_name , version % s ()) if (. not . exists ( join_path ( path_to_name , 'fpm.toml' ))) then call fatal_error ( error , \"'\" // path_to_name // \"' is missing an 'fpm.toml' file.\" ); return end if target_dir = path_to_name end subroutine get_from_local_registry !> True if dependency is part of the tree pure logical function has_dependency ( self , dependency ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( in ) :: self !> Dependency configuration to check class ( dependency_node_t ), intent ( in ) :: dependency has_dependency = self % find ( dependency % name ) /= 0 end function has_dependency !> Find a dependency in the dependency tree pure function find_name ( self , name ) result ( pos ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( in ) :: self !> Dependency configuration to add character ( len =* ), intent ( in ) :: name !> Index of the dependency integer :: pos integer :: ii pos = 0 do ii = 1 , self % ndep if ( name == self % dep ( ii )% name ) then pos = ii exit end if end do end function find_name !> Check if we are done with the dependency resolution pure function finished ( self ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( in ) :: self !> All dependencies are updated logical :: finished finished = all ( self % dep (: self % ndep )% done ) end function finished !> Update dependency from project manifest subroutine register ( self , package , root , fetch , revision , error ) !> Instance of the dependency node class ( dependency_node_t ), intent ( inout ) :: self !> Package configuration data type ( package_config_t ), intent ( in ) :: package !> Project has been fetched logical , intent ( in ) :: fetch !> Root directory of the project character ( len =* ), intent ( in ) :: root !> Git revision of the project character ( len =* ), intent ( in ), optional :: revision !> Error handling type ( error_t ), allocatable , intent ( out ) :: error logical :: update update = . false . if ( self % name /= package % name ) then call fatal_error ( error , \"Dependency name '\" // package % name // & & \"' found, but expected '\" // self % name // \"' instead\" ) end if self % version = package % version self % proj_dir = root if ( allocated ( self % git ) . and . present ( revision )) then self % revision = revision if (. not . fetch ) then ! Change in revision ID was checked already. Only update if ALL git information is missing update = . not . allocated ( self % git % url ) end if end if if ( update ) self % update = update self % done = . true . end subroutine register !> Read dependency tree from file subroutine load_cache_from_file ( self , file , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> File name character ( len =* ), intent ( in ) :: file !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: unit logical :: exist inquire ( file = file , exist = exist ) if (. not . exist ) return open ( file = file , newunit = unit ) call self % load_cache ( unit , error ) close ( unit ) end subroutine load_cache_from_file !> Read dependency tree from file subroutine load_cache_from_unit ( self , unit , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> File name integer , intent ( in ) :: unit !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_error ), allocatable :: parse_error type ( toml_table ), allocatable :: table call toml_load ( table , unit , error = parse_error ) if ( allocated ( parse_error )) then allocate ( error ) call move_alloc ( parse_error % message , error % message ) return end if call self % load_cache ( table , error ) if ( allocated ( error )) return end subroutine load_cache_from_unit !> Read dependency tree from TOML data structure subroutine load_cache_from_toml ( self , table , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ndep , ii logical :: is_unix character ( len = :), allocatable :: version , url , obj , rev , proj_dir type ( toml_key ), allocatable :: list (:) type ( toml_table ), pointer :: ptr call table % get_keys ( list ) ndep = size ( self % dep ) if ( ndep < size ( list ) + self % ndep ) then call resize ( self % dep , ndep + ndep / 2 + size ( list )) end if is_unix = get_os_type () /= OS_WINDOWS do ii = 1 , size ( list ) call get_value ( table , list ( ii )% key , ptr ) call get_value ( ptr , \"version\" , version ) call get_value ( ptr , \"proj-dir\" , proj_dir ) call get_value ( ptr , \"git\" , url ) call get_value ( ptr , \"obj\" , obj ) call get_value ( ptr , \"rev\" , rev ) if (. not . allocated ( proj_dir )) cycle self % ndep = self % ndep + 1 associate ( dep => self % dep ( self % ndep )) dep % name = list ( ii )% key if ( is_unix ) then dep % proj_dir = proj_dir else dep % proj_dir = windows_path ( proj_dir ) end if dep % done = . false . if ( allocated ( version )) then if (. not . allocated ( dep % version )) allocate ( dep % version ) call new_version ( dep % version , version , error ) if ( allocated ( error )) exit end if if ( allocated ( url )) then if ( allocated ( obj )) then dep % git = git_target_revision ( url , obj ) else dep % git = git_target_default ( url ) end if if ( allocated ( rev )) then dep % revision = rev end if else dep % path = proj_dir end if end associate end do if ( allocated ( error )) return self % ndep = size ( list ) end subroutine load_cache_from_toml !> Write dependency tree to file subroutine dump_cache_to_file ( self , file , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> File name character ( len =* ), intent ( in ) :: file !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: unit open ( file = file , newunit = unit ) call self % dump_cache ( unit , error ) close ( unit ) if ( allocated ( error )) return end subroutine dump_cache_to_file !> Write dependency tree to file subroutine dump_cache_to_unit ( self , unit , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Formatted unit integer , intent ( in ) :: unit !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ) :: table table = toml_table () call self % dump_cache ( table , error ) write ( unit , '(a)' ) toml_serialize ( table ) end subroutine dump_cache_to_unit !> Write dependency tree to TOML datastructure subroutine dump_cache_to_toml ( self , table , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ii type ( toml_table ), pointer :: ptr character ( len = :), allocatable :: proj_dir do ii = 1 , self % ndep associate ( dep => self % dep ( ii )) call add_table ( table , dep % name , ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , \"Cannot create entry for \" // dep % name ) exit end if if ( allocated ( dep % version )) then call set_value ( ptr , \"version\" , dep % version % s ()) end if proj_dir = canon_path ( dep % proj_dir ) call set_value ( ptr , \"proj-dir\" , proj_dir ) if ( allocated ( dep % git )) then call set_value ( ptr , \"git\" , dep % git % url ) if ( allocated ( dep % git % object )) then call set_value ( ptr , \"obj\" , dep % git % object ) end if if ( allocated ( dep % revision )) then call set_value ( ptr , \"rev\" , dep % revision ) end if end if end associate end do if ( allocated ( error )) return end subroutine dump_cache_to_toml !> Reallocate a list of dependencies pure subroutine resize_dependency_node ( var , n ) !> Instance of the array to be resized type ( dependency_node_t ), allocatable , intent ( inout ) :: var (:) !> Dimension of the final array size integer , intent ( in ), optional :: n type ( dependency_node_t ), allocatable :: tmp (:) integer :: this_size , new_size integer , parameter :: initial_size = 16 if ( allocated ( var )) then this_size = size ( var , 1 ) call move_alloc ( var , tmp ) else this_size = initial_size end if if ( present ( n )) then new_size = n else new_size = this_size + this_size / 2 + 1 end if allocate ( var ( new_size )) if ( allocated ( tmp )) then this_size = min ( size ( tmp , 1 ), size ( var , 1 )) var (: this_size ) = tmp (: this_size ) deallocate ( tmp ) end if end subroutine resize_dependency_node !> Check if a dependency node has changed logical function dependency_has_changed ( cached , manifest , verbosity , iunit ) result ( has_changed ) !> Two instances of the same dependency to be compared type ( dependency_node_t ), intent ( in ) :: cached , manifest !> Log verbosity integer , intent ( in ) :: verbosity , iunit integer :: ip has_changed = . true . !> All the following entities must be equal for the dependency to not have changed if ( manifest_has_changed ( cached = cached , manifest = manifest , verbosity = verbosity , iunit = iunit )) return !> For now, only perform the following checks if both are available. A dependency in cache.toml !> will always have this metadata; a dependency from fpm.toml which has not been fetched yet !> may not have it if ( allocated ( cached % version ) . and . allocated ( manifest % version )) then if ( cached % version /= manifest % version ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"VERSION has changed: \" // cached % version % s () // \" vs. \" // manifest % version % s () return end if else if ( verbosity > 1 ) write ( iunit , out_fmt ) \"VERSION has changed presence \" end if if ( allocated ( cached % revision ) . and . allocated ( manifest % revision )) then if ( cached % revision /= manifest % revision ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"REVISION has changed: \" // cached % revision // \" vs. \" // manifest % revision return end if else if ( verbosity > 1 ) write ( iunit , out_fmt ) \"REVISION has changed presence \" end if if ( allocated ( cached % proj_dir ) . and . allocated ( manifest % proj_dir )) then if ( cached % proj_dir /= manifest % proj_dir ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PROJECT DIR has changed: \" // cached % proj_dir // \" vs. \" // manifest % proj_dir return end if else if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PROJECT DIR has changed presence \" end if if ( allocated ( cached % preprocess ) . eqv . allocated ( manifest % preprocess )) then if ( allocated ( cached % preprocess )) then if ( size ( cached % preprocess ) /= size ( manifest % preprocess )) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PREPROCESS has changed size\" return end if do ip = 1 , size ( cached % preprocess ) if (. not .( cached % preprocess ( ip ) == manifest % preprocess ( ip ))) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PREPROCESS config has changed\" return end if end do endif else if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PREPROCESS has changed presence \" return end if !> All checks passed: the two dependencies have no differences has_changed = . false . end function dependency_has_changed !> Check that two dependency nodes are equal logical function dependency_node_is_same ( this , that ) class ( dependency_node_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that dependency_node_is_same = . false . select type ( other => that ) type is ( dependency_node_t ) ! Base class must match if (. not .( this % dependency_config_t == other % dependency_config_t )) return ! Extension must match if (. not .( this % done . eqv . other % done )) return if (. not .( this % update . eqv . other % update )) return if (. not .( this % cached . eqv . other % cached )) return if (. not .( this % proj_dir == other % proj_dir )) return if (. not .( this % revision == other % revision )) return if (. not .( allocated ( this % version ). eqv . allocated ( other % version ))) return if ( allocated ( this % version )) then if (. not .( this % version == other % version )) return endif class default ! Not the same type return end select !> All checks passed! dependency_node_is_same = . true . end function dependency_node_is_same !> Dump dependency to toml table subroutine node_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_node_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr ! Dump parent class call self % dependency_config_t % dump_to_toml ( table , error ) if ( allocated ( error )) return if ( allocated ( self % version )) then call set_string ( table , \"version\" , self % version % s (), error , 'dependency_node_t' ) if ( allocated ( error )) return endif call set_string ( table , \"proj-dir\" , self % proj_dir , error , 'dependency_node_t' ) if ( allocated ( error )) return call set_string ( table , \"revision\" , self % revision , error , 'dependency_node_t' ) if ( allocated ( error )) return call set_value ( table , \"done\" , self % done , error , 'dependency_node_t' ) if ( allocated ( error )) return call set_value ( table , \"update\" , self % update , error , 'dependency_node_t' ) if ( allocated ( error )) return call set_value ( table , \"cached\" , self % cached , error , 'dependency_node_t' ) if ( allocated ( error )) return end subroutine node_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine node_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_node_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: version integer :: ierr call destroy_dependency_node ( self ) ! Load parent class call self % dependency_config_t % load_from_toml ( table , error ) if ( allocated ( error )) return call get_value ( table , \"done\" , self % done , error , 'dependency_node_t' ) if ( allocated ( error )) return call get_value ( table , \"update\" , self % update , error , 'dependency_node_t' ) if ( allocated ( error )) return call get_value ( table , \"cached\" , self % cached , error , 'dependency_node_t' ) if ( allocated ( error )) return call get_value ( table , \"proj-dir\" , self % proj_dir ) call get_value ( table , \"revision\" , self % revision ) call get_value ( table , \"version\" , version ) if ( allocated ( version )) then allocate ( self % version ) call new_version ( self % version , version , error ) if ( allocated ( error )) then error % message = 'dependency_node_t: version error from TOML table - ' // error % message return endif end if end subroutine node_load_from_toml !> Destructor elemental subroutine destroy_dependency_node ( self ) class ( dependency_node_t ), intent ( inout ) :: self integer :: ierr call dependency_destroy ( self ) deallocate ( self % version , stat = ierr ) deallocate ( self % proj_dir , stat = ierr ) deallocate ( self % revision , stat = ierr ) self % done = . false . self % update = . false . self % cached = . false . end subroutine destroy_dependency_node !> Check that two dependency trees are equal logical function dependency_tree_is_same ( this , that ) class ( dependency_tree_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii dependency_tree_is_same = . false . select type ( other => that ) type is ( dependency_tree_t ) if (. not .( this % unit == other % unit )) return if (. not .( this % verbosity == other % verbosity )) return if (. not .( this % dep_dir == other % dep_dir )) return if (. not .( this % ndep == other % ndep )) return if (. not .( allocated ( this % dep ). eqv . allocated ( other % dep ))) return if ( allocated ( this % dep )) then if (. not .( size ( this % dep ) == size ( other % dep ))) return do ii = 1 , size ( this % dep ) if (. not .( this % dep ( ii ) == other % dep ( ii ))) return end do endif if (. not .( this % cache == other % cache )) return class default ! Not the same type return end select !> All checks passed! dependency_tree_is_same = . true . end function dependency_tree_is_same !> Dump dependency to toml table subroutine tree_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_tree_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii type ( toml_table ), pointer :: ptr_deps , ptr character ( 27 ) :: unnamed call set_value ( table , \"unit\" , self % unit , error , 'dependency_tree_t' ) if ( allocated ( error )) return call set_value ( table , \"verbosity\" , self % verbosity , error , 'dependency_tree_t' ) if ( allocated ( error )) return call set_string ( table , \"dep-dir\" , self % dep_dir , error , 'dependency_tree_t' ) if ( allocated ( error )) return call set_string ( table , \"cache\" , self % cache , error , 'dependency_tree_t' ) if ( allocated ( error )) return call set_value ( table , \"ndep\" , self % ndep , error , 'dependency_tree_t' ) if ( allocated ( error )) return if ( allocated ( self % dep )) then ! Create dependency table call add_table ( table , \"dependencies\" , ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , \"dependency_tree_t cannot create dependency table \" ) return end if do ii = 1 , size ( self % dep ) associate ( dep => self % dep ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( dep % name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_deps , trim ( unnamed ), ptr ) else call add_table ( ptr_deps , dep % name , ptr ) end if if (. not . associated ( ptr )) then call fatal_error ( error , \"dependency_tree_t cannot create entry for dependency \" // dep % name ) return end if call dep % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do endif 1 format ( 'UNNAMED_DEPENDENCY_' , i0 ) end subroutine tree_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine tree_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_tree_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables type ( toml_key ), allocatable :: keys (:), dep_keys (:) type ( toml_table ), pointer :: ptr_deps , ptr integer :: ii , jj , ierr call table % get_keys ( keys ) call get_value ( table , \"unit\" , self % unit , error , 'dependency_tree_t' ) if ( allocated ( error )) return call get_value ( table , \"verbosity\" , self % verbosity , error , 'dependency_tree_t' ) if ( allocated ( error )) return call get_value ( table , \"ndep\" , self % ndep , error , 'dependency_tree_t' ) if ( allocated ( error )) return call get_value ( table , \"dep-dir\" , self % dep_dir ) call get_value ( table , \"cache\" , self % cache ) find_deps_table : do ii = 1 , size ( keys ) if ( keys ( ii )% key == \"dependencies\" ) then call get_value ( table , keys ( ii ), ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , 'dependency_tree_t: error retrieving dependency table from TOML table' ) return end if !> Read all dependencies call ptr_deps % get_keys ( dep_keys ) call resize ( self % dep , size ( dep_keys )) do jj = 1 , size ( dep_keys ) call get_value ( ptr_deps , dep_keys ( jj ), ptr ) call self % dep ( jj )% load_from_toml ( ptr , error ) if ( allocated ( error )) return end do exit find_deps_table endif end do find_deps_table end subroutine tree_load_from_toml end module fpm_dependency","tags":"","loc":"sourcefile/dependency.f90~2.html"},{"title":"fpm_release.F90 – Fortran-lang/fpm","text":"Source Code !># Release parameters !> Module fpm_release contains public constants storing this build's unique version IDs module fpm_release use fpm_versioning , only : version_t , new_version use fpm_error , only : error_t , fpm_stop implicit none private public :: fpm_version public :: version_t contains !> Return the current fpm version from fpm_version_ID as a version type type ( version_t ) function fpm_version () type ( error_t ), allocatable :: error ! Fallback to last known version in case of undefined macro #ifndef FPM_RELEASE_VERSION # define FPM_RELEASE_VERSION 0.10.1 #endif ! Accept solution from https://stackoverflow.com/questions/31649691/stringify-macro-with-gnu-gfortran ! which provides the \"easiest\" way to pass a macro to a string in Fortran complying with both ! gfortran's \"traditional\" cpp and the standard cpp syntaxes #ifdef __GFORTRAN__ /* traditional-cpp stringification */ # define STRINGIFY_START(X) \"& # define STRINGIFY_END(X) &X\" #else /* default stringification */ # define STRINGIFY_(X) #X # define STRINGIFY_START(X) & # define STRINGIFY_END(X) STRINGIFY_(X) #endif character ( len = :), allocatable :: ver_string ver_string = STRINGIFY_START ( FPM_RELEASE_VERSION ) STRINGIFY_END ( FPM_RELEASE_VERSION ) call new_version ( fpm_version , ver_string , error ) if ( allocated ( error )) call fpm_stop ( 1 , '*fpm*:internal error: cannot get version - ' // error % message ) end function fpm_version end module fpm_release","tags":"","loc":"sourcefile/fpm_release.f90.html"},{"title":"preprocess.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for preprocessing. !> !> A preprocess table can currently have the following fields !> !> ```toml !> [preprocess] !> [preprocess.cpp] !> suffixes = [\"F90\", \"f90\"] !> directories = [\"src/feature1\", \"src/models\"] !> macros = [] !> ``` module fpm_manifest_preprocess use fpm_error , only : error_t , syntax_error use fpm_strings , only : string_t , operator ( == ) use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list , serializable_t , set_value , set_list , & set_string use , intrinsic :: iso_fortran_env , only : stderr => error_unit implicit none private public :: preprocess_config_t , new_preprocess_config , new_preprocessors , operator ( == ) !> Configuration meta data for a preprocessor type , extends ( serializable_t ) :: preprocess_config_t !> Name of the preprocessor character ( len = :), allocatable :: name !> Suffixes of the files to be preprocessed type ( string_t ), allocatable :: suffixes (:) !> Directories to search for files to be preprocessed type ( string_t ), allocatable :: directories (:) !> Macros to be defined for the preprocessor type ( string_t ), allocatable :: macros (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => preprocess_is_same procedure :: dump_to_toml procedure :: load_from_toml !> Operations procedure :: destroy procedure :: add_config !> Properties procedure :: is_cpp procedure :: is_fypp end type preprocess_config_t character ( * ), parameter , private :: class_name = 'preprocess_config_t' contains !> Construct a new preprocess configuration from TOML data structure subroutine new_preprocess_config ( self , table , error ) !> Instance of the preprocess configuration type ( preprocess_config_t ), intent ( out ) :: self !> Instance of the TOML data structure. type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call table % get_key ( self % name ) call get_list ( table , \"suffixes\" , self % suffixes , error ) if ( allocated ( error )) return call get_list ( table , \"directories\" , self % directories , error ) if ( allocated ( error )) return call get_list ( table , \"macros\" , self % macros , error ) if ( allocated ( error )) return end subroutine new_preprocess_config !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure. type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( inout ) :: error character ( len = :), allocatable :: name type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_key ( name ) call table % get_keys ( list ) do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) !> Valid keys. case ( \"suffixes\" , \"directories\" , \"macros\" ) case default call syntax_error ( error , \"Key '\" // list ( ikey )% key // \"' not allowed in preprocessor '\" // name // \"'.\" ); exit end select end do end subroutine check !> Construct new preprocess array from a TOML data structure. subroutine new_preprocessors ( preprocessors , table , error ) !> Instance of the preprocess configuration type ( preprocess_config_t ), allocatable , intent ( out ) :: preprocessors (:) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: node type ( toml_key ), allocatable :: list (:) integer :: iprep , stat call table % get_keys ( list ) ! An empty table is not allowed if ( size ( list ) == 0 ) then call syntax_error ( error , \"No preprocessors defined\" ) end if allocate ( preprocessors ( size ( list ))) do iprep = 1 , size ( list ) call get_value ( table , list ( iprep )% key , node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Preprocessor \" // list ( iprep )% key // \" must be a table entry\" ) exit end if call new_preprocess_config ( preprocessors ( iprep ), node , error ) if ( allocated ( error )) exit end do end subroutine new_preprocessors !> Write information on this instance subroutine info ( self , unit , verbosity ) !> Instance of the preprocess configuration class ( preprocess_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ilink character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Preprocessor\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % suffixes )) then write ( unit , fmt ) \" - suffixes\" do ilink = 1 , size ( self % suffixes ) write ( unit , fmt ) \" - \" // self % suffixes ( ilink )% s end do end if if ( allocated ( self % directories )) then write ( unit , fmt ) \" - directories\" do ilink = 1 , size ( self % directories ) write ( unit , fmt ) \" - \" // self % directories ( ilink )% s end do end if if ( allocated ( self % macros )) then write ( unit , fmt ) \" - macros\" do ilink = 1 , size ( self % macros ) write ( unit , fmt ) \" - \" // self % macros ( ilink )% s end do end if end subroutine info logical function preprocess_is_same ( this , that ) class ( preprocess_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: istr preprocess_is_same = . false . select type ( other => that ) type is ( preprocess_config_t ) if ( allocated ( this % name ). neqv . allocated ( other % name )) return if ( allocated ( this % name )) then if (. not .( this % name == other % name )) return endif if (. not .( this % suffixes == other % suffixes )) return if (. not .( this % directories == other % directories )) return if (. not .( this % macros == other % macros )) return class default ! Not the same type return end select !> All checks passed! preprocess_is_same = . true . end function preprocess_is_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( preprocess_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_string ( table , \"name\" , self % name , error ) if ( allocated ( error )) return call set_list ( table , \"suffixes\" , self % suffixes , error ) if ( allocated ( error )) return call set_list ( table , \"directories\" , self % directories , error ) if ( allocated ( error )) return call set_list ( table , \"macros\" , self % macros , error ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( preprocess_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"name\" , self % name ) call get_list ( table , \"suffixes\" , self % suffixes , error ) if ( allocated ( error )) return call get_list ( table , \"directories\" , self % directories , error ) if ( allocated ( error )) return call get_list ( table , \"macros\" , self % macros , error ) if ( allocated ( error )) return end subroutine load_from_toml !> Clean preprocessor structure elemental subroutine destroy ( this ) class ( preprocess_config_t ), intent ( inout ) :: this if ( allocated ( this % name )) deallocate ( this % name ) if ( allocated ( this % suffixes )) deallocate ( this % suffixes ) if ( allocated ( this % directories )) deallocate ( this % directories ) if ( allocated ( this % macros )) deallocate ( this % macros ) end subroutine destroy !> Add preprocessor settings subroutine add_config ( this , that ) class ( preprocess_config_t ), intent ( inout ) :: this type ( preprocess_config_t ), intent ( in ) :: that if (. not . that % is_cpp ()) then write ( stderr , '(a)' ) 'Warning: Preprocessor ' // that % name // & ' is not supported; will ignore it' return end if if (. not . allocated ( this % name )) this % name = that % name ! Add macros if ( allocated ( that % macros )) then if ( allocated ( this % macros )) then this % macros = [ this % macros , that % macros ] else allocate ( this % macros , source = that % macros ) end if endif ! Add suffixes if ( allocated ( that % suffixes )) then if ( allocated ( this % suffixes )) then this % suffixes = [ this % suffixes , that % suffixes ] else allocate ( this % suffixes , source = that % suffixes ) end if endif ! Add directories if ( allocated ( that % directories )) then if ( allocated ( this % directories )) then this % directories = [ this % directories , that % directories ] else allocate ( this % directories , source = that % directories ) end if endif end subroutine add_config ! Check cpp logical function is_cpp ( this ) class ( preprocess_config_t ), intent ( in ) :: this is_cpp = . false . if ( allocated ( this % name )) is_cpp = this % name == \"cpp\" end function is_cpp ! Check cpp logical function is_fypp ( this ) class ( preprocess_config_t ), intent ( in ) :: this is_fypp = . false . if ( allocated ( this % name )) is_fypp = this % name == \"fypp\" end function is_fypp end module fpm_manifest_preprocess","tags":"","loc":"sourcefile/preprocess.f90.html"},{"title":"publish.f90 – Fortran-lang/fpm","text":"Source Code !> Upload a package to the registry using the `publish` command. !> !> To upload a package you need to provide a token that will be linked to your username and created for a namespace. !> The token can be obtained from the registry website. It can be used as `fpm publish --token `. module fpm_cmd_publish use fpm_command_line , only : fpm_publish_settings use fpm_manifest , only : package_config_t , get_package_data use fpm_model , only : fpm_model_t use fpm_error , only : error_t , fpm_stop use fpm_versioning , only : version_t use fpm_filesystem , only : exists , join_path , get_temp_filename , delete_file use fpm_git , only : git_archive use fpm_downloader , only : downloader_t use fpm_strings , only : string_t use fpm_settings , only : official_registry_base_url use fpm , only : build_model implicit none private public :: cmd_publish contains !> The `publish` command first builds the root package to obtain all the relevant information such as the !> package version. It then creates a tarball of the package and uploads it to the registry. subroutine cmd_publish ( settings ) type ( fpm_publish_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( error_t ), allocatable :: error type ( version_t ), allocatable :: version type ( string_t ), allocatable :: upload_data (:) character ( len = :), allocatable :: tmp_file type ( downloader_t ) :: downloader integer :: i ! Get package data to determine package version. call get_package_data ( package , 'fpm.toml' , error , apply_defaults = . true .) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_build* Package error: ' // error % message ) version = package % version if ( settings % show_package_version ) then print * , version % s (); return end if !> Checks before uploading the package. if (. not . allocated ( package % license )) call fpm_stop ( 1 , 'No license specified in fpm.toml.' ) if (. not . package % build % module_naming ) call fpm_stop ( 1 , 'The package does not meet the module naming requirements. ' // & & 'Please set \"module-naming = true\" in fpm.toml [build] or specify a custom module prefix.' ) if (. not . allocated ( version )) call fpm_stop ( 1 , 'No version specified in fpm.toml.' ) if ( version % s () == '0' ) call fpm_stop ( 1 , 'Invalid version: \"' // version % s () // '\".' ) if (. not . exists ( 'fpm.toml' )) call fpm_stop ( 1 , \"Cannot find 'fpm.toml' file. Are you in the project root?\" ) ! Build model to obtain dependency tree. call build_model ( model , settings % fpm_build_settings , package , error ) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_build* Model error: ' // error % message ) ! Check if package contains git dependencies. Only publish packages without git dependencies. do i = 1 , model % deps % ndep if ( allocated ( model % deps % dep ( i )% git )) then call fpm_stop ( 1 , 'Do not publish packages containing git dependencies. ' // & & \"Please upload '\" // model % deps % dep ( i )% name // \"' to the registry first.\" ) end if end do tmp_file = get_temp_filename () call git_archive ( '.' , tmp_file , 'HEAD' , additional_files = [ 'fpm_model.json' ], verbose = settings % verbose , error = error ) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_publish* Archive error: ' // error % message ) call model % dump ( 'fpm_model.json' , error , json = . true .) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_publish* Model dump error: ' // error % message ) upload_data = [ & & string_t ( 'package_name=\"' // package % name // '\"' ), & & string_t ( 'package_license=\"' // package % license // '\"' ), & & string_t ( 'package_version=\"' // version % s () // '\"' ), & & string_t ( 'tarball=@\"' // tmp_file // '\"' ) & & ] if ( allocated ( settings % token )) upload_data = [ upload_data , string_t ( 'upload_token=\"' // settings % token // '\"' )] if ( settings % show_upload_data ) then call print_upload_data ( upload_data ); return end if ! Make sure a token is provided for publishing. if ( allocated ( settings % token )) then if ( settings % token == '' ) then call delete_file ( tmp_file ); call fpm_stop ( 1 , 'No token provided.' ) end if else call delete_file ( tmp_file ); call fpm_stop ( 1 , 'No token provided.' ) end if if ( settings % verbose ) then call print_upload_data ( upload_data ) print * , '' end if ! Perform network request and validate package, token etc. on the backend once ! https://github.com/fortran-lang/registry/issues/41 is resolved. if ( settings % is_dry_run ) then print * , 'Dry run successful. Generated tarball: ' , tmp_file ; return end if call downloader % upload_form ( official_registry_base_url // '/packages' , upload_data , settings % verbose , error ) call delete_file ( tmp_file ) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_publish* Upload error: ' // error % message ) end subroutine print_upload_data ( upload_data ) type ( string_t ), intent ( in ) :: upload_data (:) integer :: i print * , 'Upload data:' do i = 1 , size ( upload_data ) print * , upload_data ( i )% s end do end end","tags":"","loc":"sourcefile/publish.f90.html"},{"title":"fpm_settings.f90 – Fortran-lang/fpm","text":"Source Code !> Manages global settings which are defined in the global config file. module fpm_settings use fpm_filesystem , only : exists , join_path , get_local_prefix , is_absolute_path , mkdir use fpm_environment , only : os_is_unix use fpm_error , only : error_t , fatal_error use fpm_toml , only : toml_table , toml_error , toml_stat , get_value , toml_load , check_keys use fpm_os , only : get_current_directory , change_directory , get_absolute_path , convert_to_absolute_path implicit none private public :: fpm_global_settings , get_global_settings , get_registry_settings , official_registry_base_url character ( * ), parameter :: official_registry_base_url = 'https://fpm-registry.vercel.app' character ( * ), parameter :: default_config_file_name = 'config.toml' type :: fpm_global_settings !> Path to the global config file excluding the file name. character ( len = :), allocatable :: path_to_config_folder !> Name of the global config file. The default is `config.toml`. character ( len = :), allocatable :: config_file_name !> Registry configs. type ( fpm_registry_settings ), allocatable :: registry_settings contains procedure :: has_custom_location , full_path , path_to_config_folder_or_empty end type type :: fpm_registry_settings !> The path to the local registry. If allocated, the local registry !> will be used instead of the remote registry and replaces the !> local cache. character ( len = :), allocatable :: path !> The URL to the remote registry. Can be used to get packages !> from the official or a custom registry. character ( len = :), allocatable :: url !> The path to the cache folder. If not specified, the default cache !> folders are `~/.local/share/fpm/dependencies` on Unix and !> `%APPDATA%\\local\\fpm\\dependencies` on Windows. !> Cannot be used together with `path`. character ( len = :), allocatable :: cache_path end type contains !> Obtain global settings from the global config file. subroutine get_global_settings ( global_settings , error ) !> Global settings to be obtained. type ( fpm_global_settings ), intent ( inout ) :: global_settings !> Error reading config file. type ( error_t ), allocatable , intent ( out ) :: error !> TOML table to be filled with global config settings. type ( toml_table ), allocatable :: table !> Error parsing to TOML table. type ( toml_error ), allocatable :: parse_error type ( toml_table ), pointer :: registry_table integer :: stat ! Use custom path to the config file if it was specified. if ( global_settings % has_custom_location ()) then ! Throw error if folder doesn't exist. if (. not . exists ( global_settings % path_to_config_folder )) then call fatal_error ( error , \"Folder not found: '\" // global_settings % path_to_config_folder // \"'.\" ); return end if ! Throw error if the file doesn't exist. if (. not . exists ( global_settings % full_path ())) then call fatal_error ( error , \"File not found: '\" // global_settings % full_path () // \"'.\" ); return end if ! Make sure that the path to the global config file is absolute. call convert_to_absolute_path ( global_settings % path_to_config_folder , error ) if ( allocated ( error )) return else ! Use default path if it wasn't specified. if ( os_is_unix ()) then global_settings % path_to_config_folder = join_path ( get_local_prefix (), 'share' , 'fpm' ) else global_settings % path_to_config_folder = join_path ( get_local_prefix (), 'fpm' ) end if ! Use default file name. global_settings % config_file_name = default_config_file_name ! Apply default registry settings and return if config file doesn't exist. if (. not . exists ( global_settings % full_path ())) then call use_default_registry_settings ( global_settings ); return end if end if ! Load into TOML table. call toml_load ( table , global_settings % full_path (), error = parse_error ) if ( allocated ( parse_error )) then allocate ( error ); call move_alloc ( parse_error % message , error % message ); return end if call get_value ( table , 'registry' , registry_table , requested = . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error reading registry from config file '\" // & & global_settings % full_path () // \"'.\" ); return end if ! A registry table was found. if ( associated ( registry_table )) then call get_registry_settings ( registry_table , global_settings , error ) else call use_default_registry_settings ( global_settings ) end if end !> Default registry settings are typically applied if the config file doesn't exist or no registry table was found in !> the global config file. subroutine use_default_registry_settings ( global_settings ) type ( fpm_global_settings ), intent ( inout ) :: global_settings if (. not . allocated ( global_settings % registry_settings )) allocate ( global_settings % registry_settings ) global_settings % registry_settings % url = official_registry_base_url global_settings % registry_settings % cache_path = join_path ( global_settings % path_to_config_folder_or_empty (), & & 'dependencies' ) end !> Read registry settings from the global config file. subroutine get_registry_settings ( table , global_settings , error ) !> The [registry] subtable from the global config file. type ( toml_table ), target , intent ( inout ) :: table !> The global settings which can be filled with the registry settings. type ( fpm_global_settings ), intent ( inout ) :: global_settings !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error character (:), allocatable :: path , url , cache_path integer :: stat !> List of valid keys for the dependency table. character ( * ), dimension ( * ), parameter :: valid_keys = [ character ( 10 ) :: & & 'path' , & & 'url' , & & 'cache_path' & & ] call check_keys ( table , valid_keys , error ) if ( allocated ( error )) return allocate ( global_settings % registry_settings ) if ( table % has_key ( 'path' )) then call get_value ( table , 'path' , path , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error reading registry path: '\" // path // \"'.\" ); return end if end if if ( allocated ( path )) then if ( is_absolute_path ( path )) then global_settings % registry_settings % path = path else ! Get canonical, absolute path on both Unix and Windows. call get_absolute_path ( join_path ( global_settings % path_to_config_folder_or_empty (), path ), & & global_settings % registry_settings % path , error ) if ( allocated ( error )) return ! Check if the path to the registry exists. if (. not . exists ( global_settings % registry_settings % path )) then call fatal_error ( error , \"Directory '\" // global_settings % registry_settings % path // & & \"' doesn't exist.\" ); return end if end if end if if ( table % has_key ( 'url' )) then call get_value ( table , 'url' , url , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error reading registry url: '\" // url // \"'.\" ); return end if end if if ( allocated ( url )) then ! Throw error when both path and url were provided. if ( allocated ( path )) then call fatal_error ( error , 'Do not provide both path and url to the registry.' ); return end if global_settings % registry_settings % url = url else if (. not . allocated ( path )) then global_settings % registry_settings % url = official_registry_base_url end if if ( table % has_key ( 'cache_path' )) then call get_value ( table , 'cache_path' , cache_path , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error reading path to registry cache: '\" // cache_path // \"'.\" ); return end if end if if ( allocated ( cache_path )) then ! Throw error when both path and cache_path were provided. if ( allocated ( path )) then call fatal_error ( error , \"Do not provide both 'path' and 'cache_path'.\" ); return end if if ( is_absolute_path ( cache_path )) then if (. not . exists ( cache_path )) call mkdir ( cache_path ) global_settings % registry_settings % cache_path = cache_path else cache_path = join_path ( global_settings % path_to_config_folder_or_empty (), cache_path ) if (. not . exists ( cache_path )) call mkdir ( cache_path ) ! Get canonical, absolute path on both Unix and Windows. call get_absolute_path ( cache_path , global_settings % registry_settings % cache_path , error ) if ( allocated ( error )) return end if else if (. not . allocated ( path )) then global_settings % registry_settings % cache_path = & join_path ( global_settings % path_to_config_folder_or_empty (), 'dependencies' ) end if end !> True if the global config file is not at the default location. elemental logical function has_custom_location ( self ) class ( fpm_global_settings ), intent ( in ) :: self has_custom_location = allocated ( self % path_to_config_folder ) . and . allocated ( self % config_file_name ) if (. not . has_custom_location ) return has_custom_location = len_trim ( self % path_to_config_folder ) > 0 . and . len_trim ( self % config_file_name ) > 0 end !> The full path to the global config file. function full_path ( self ) result ( result ) class ( fpm_global_settings ), intent ( in ) :: self character ( len = :), allocatable :: result result = join_path ( self % path_to_config_folder_or_empty (), self % config_file_name ) end !> The path to the global config directory. pure function path_to_config_folder_or_empty ( self ) class ( fpm_global_settings ), intent ( in ) :: self character ( len = :), allocatable :: path_to_config_folder_or_empty if ( allocated ( self % path_to_config_folder )) then path_to_config_folder_or_empty = self % path_to_config_folder else path_to_config_folder_or_empty = \"\" end if end end","tags":"","loc":"sourcefile/fpm_settings.f90.html"},{"title":"fpm_model.f90 – Fortran-lang/fpm","text":"Source Code !># The fpm package model !> !> Defines the fpm model data types which encapsulate all information !> required to correctly build a package and its dependencies. !> !> The process (see `[[build_model(subroutine)]]`) for generating a valid `[[fpm_model]]` involves !> source files discovery ([[fpm_sources]]) and parsing ([[fpm_source_parsing]]). !> !> Once a valid `[[fpm_model]]` has been constructed, it may be passed to `[[fpm_targets:targets_from_sources]]` to !> generate a list of build targets for the backend. !> !>### Enumerations !> !> __Source type:__ `FPM_UNIT_*` !> Describes the type of source file — determines build target generation !> !> The logical order of precedence for assigning `unit_type` is as follows: !> !>``` !> if source-file contains program then !> unit_type = FPM_UNIT_PROGRAM !> else if source-file contains non-module subroutine/function then !> unit_type = FPM_UNIT_SUBPROGRAM !> else if source-file contains submodule then !> unit_type = FPM_UNIT_SUBMODULE !> else if source-file contains module then !> unit_type = FPM_UNIT_MODULE !> end if !>``` !> !> @note A source file is only designated `FPM_UNIT_MODULE` if it **only** contains modules - no non-module subprograms. !> (This allows tree-shaking/pruning of build targets based on unused module dependencies.) !> !> __Source scope:__ `FPM_SCOPE_*` !> Describes the scoping rules for using modules — controls module dependency resolution !> module fpm_model use iso_fortran_env , only : int64 use fpm_compiler , only : compiler_t , archiver_t , debug use fpm_dependency , only : dependency_tree_t use fpm_strings , only : string_t , str , len_trim , upper , operator ( == ) use fpm_toml , only : serializable_t , toml_table , toml_stat , set_value , set_list , get_value , & & get_list , add_table , toml_key , add_array , set_string use fpm_error , only : error_t , fatal_error use fpm_manifest_preprocess , only : preprocess_config_t implicit none private public :: fpm_model_t , srcfile_t , show_model , fortran_features_t , package_t public :: FPM_UNIT_UNKNOWN , FPM_UNIT_PROGRAM , FPM_UNIT_MODULE , & FPM_UNIT_SUBMODULE , FPM_UNIT_SUBPROGRAM , FPM_UNIT_CSOURCE , & FPM_UNIT_CHEADER , FPM_SCOPE_UNKNOWN , FPM_SCOPE_LIB , & FPM_SCOPE_DEP , FPM_SCOPE_APP , FPM_SCOPE_EXAMPLE , FPM_SCOPE_TEST , & FPM_UNIT_CPPSOURCE , FPM_SCOPE_NAME !> Source type unknown integer , parameter :: FPM_UNIT_UNKNOWN = - 1 !> Source contains a fortran program integer , parameter :: FPM_UNIT_PROGRAM = 1 !> Source **only** contains one or more fortran modules integer , parameter :: FPM_UNIT_MODULE = 2 !> Source contains one or more fortran submodules integer , parameter :: FPM_UNIT_SUBMODULE = 3 !> Source contains one or more fortran subprogram not within modules integer , parameter :: FPM_UNIT_SUBPROGRAM = 4 !> Source type is c source file integer , parameter :: FPM_UNIT_CSOURCE = 5 !> Source type is c header file integer , parameter :: FPM_UNIT_CHEADER = 6 !> Souce type is c++ source file. integer , parameter :: FPM_UNIT_CPPSOURCE = 7 !> Source has no module-use scope integer , parameter :: FPM_SCOPE_UNKNOWN = - 1 !> Module-use scope is library/dependency modules only integer , parameter :: FPM_SCOPE_LIB = 1 !> Module-use scope is library/dependency modules only integer , parameter :: FPM_SCOPE_DEP = 2 !> Module-use scope is library/dependency and app modules integer , parameter :: FPM_SCOPE_APP = 3 !> Module-use scope is library/dependency and test modules integer , parameter :: FPM_SCOPE_TEST = 4 integer , parameter :: FPM_SCOPE_EXAMPLE = 5 !> Enabled Fortran language features type , extends ( serializable_t ) :: fortran_features_t !> Use default implicit typing logical :: implicit_typing = . false . !> Use implicit external interface logical :: implicit_external = . false . !> Form to use for all Fortran sources character (:), allocatable :: source_form contains !> Serialization interface procedure :: serializable_is_same => fft_is_same procedure :: dump_to_toml => fft_dump_to_toml procedure :: load_from_toml => fft_load_from_toml end type fortran_features_t !> Type for describing a source file type , extends ( serializable_t ) :: srcfile_t !> File path relative to cwd character (:), allocatable :: file_name !> Name of executable for FPM_UNIT_PROGRAM character (:), allocatable :: exe_name !> Target module-use scope integer :: unit_scope = FPM_SCOPE_UNKNOWN !> Modules provided by this source file (lowerstring) type ( string_t ), allocatable :: modules_provided (:) !> Type of source unit integer :: unit_type = FPM_UNIT_UNKNOWN !> Parent modules (submodules only) type ( string_t ), allocatable :: parent_modules (:) !> Modules USEd by this source file (lowerstring) type ( string_t ), allocatable :: modules_used (:) !> Files INCLUDEd by this source file type ( string_t ), allocatable :: include_dependencies (:) !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> Current hash integer ( int64 ) :: digest contains !> Serialization interface procedure :: serializable_is_same => srcfile_is_same procedure :: dump_to_toml => srcfile_dump_to_toml procedure :: load_from_toml => srcfile_load_from_toml end type srcfile_t !> Type for describing a single package type , extends ( serializable_t ) :: package_t !> Name of package character (:), allocatable :: name !> Array of sources type ( srcfile_t ), allocatable :: sources (:) !> List of macros. type ( preprocess_config_t ) :: preprocess !> Package version number. character (:), allocatable :: version !> Module naming conventions logical :: enforce_module_names = . false . !> Prefix for all module names type ( string_t ) :: module_prefix !> Language features type ( fortran_features_t ) :: features contains !> Serialization interface procedure :: serializable_is_same => package_is_same procedure :: dump_to_toml => package_dump_to_toml procedure :: load_from_toml => package_load_from_toml end type package_t !> Type describing everything required to build !> the root package and its dependencies. type , extends ( serializable_t ) :: fpm_model_t !> Name of root package character (:), allocatable :: package_name !> Array of packages (including the root package) type ( package_t ), allocatable :: packages (:) !> Compiler object type ( compiler_t ) :: compiler !> Archiver object type ( archiver_t ) :: archiver !> Command line flags passed to fortran for compilation character (:), allocatable :: fortran_compile_flags !> Command line flags passed to C for compilation character (:), allocatable :: c_compile_flags !> Command line flags passed to C++ for compilation character (:), allocatable :: cxx_compile_flags !> Command line flags passed to the linker character (:), allocatable :: link_flags !> Base directory for build character (:), allocatable :: build_prefix !> Include directories type ( string_t ), allocatable :: include_dirs (:) !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> External modules used type ( string_t ), allocatable :: external_modules (:) !> Project dependencies type ( dependency_tree_t ) :: deps !> Whether tests should be added to the build list logical :: include_tests = . true . !> Whether module names should be prefixed with the package name logical :: enforce_module_names = . false . !> Prefix for all module names type ( string_t ) :: module_prefix contains !> Serialization interface procedure :: serializable_is_same => model_is_same procedure :: dump_to_toml => model_dump_to_toml procedure :: load_from_toml => model_load_from_toml end type fpm_model_t contains function info_package ( p ) result ( s ) ! Returns representation of package_t type ( package_t ), intent ( in ) :: p character (:), allocatable :: s integer :: i s = s // 'package_t(' s = s // 'name=\"' // p % name // '\"' s = s // ', sources=[' do i = 1 , size ( p % sources ) s = s // info_srcfile ( p % sources ( i )) if ( i < size ( p % sources )) s = s // \", \" end do s = s // \"]\" ! Print module naming convention s = s // ', enforce_module_names=\"' // merge ( 'T' , 'F' , p % enforce_module_names ) // '\"' ! Print custom prefix if ( p % enforce_module_names . and . len_trim ( p % module_prefix ) > 0 ) & s = s // ', custom_prefix=\"' // p % module_prefix % s // '\"' s = s // \")\" end function info_package function info_srcfile ( source ) result ( s ) type ( srcfile_t ), intent ( in ) :: source character (:), allocatable :: s integer :: i !type srcfile_t s = \"srcfile_t(\" ! character(:), allocatable :: file_name s = s // 'file_name=\"' // source % file_name // '\"' ! character(:), allocatable :: exe_name s = s // ', exe_name=\"' // source % exe_name // '\"' ! integer :: unit_scope = FPM_SCOPE_UNKNOWN s = s // ', unit_scope=\"' // FPM_SCOPE_NAME ( source % unit_scope ) // '\"' ! type(string_t), allocatable :: modules_provided(:) s = s // \", modules_provided=[\" do i = 1 , size ( source % modules_provided ) s = s // '\"' // source % modules_provided ( i )% s // '\"' if ( i < size ( source % modules_provided )) s = s // \", \" end do s = s // \"]\" s = s // \", parent_modules=[\" do i = 1 , size ( source % parent_modules ) s = s // '\"' // source % parent_modules ( i )% s // '\"' if ( i < size ( source % parent_modules )) s = s // \", \" end do s = s // \"]\" ! integer :: unit_type = FPM_UNIT_UNKNOWN s = s // ', unit_type=\"' // FPM_UNIT_NAME ( source % unit_type ) // '\"' ! type(string_t), allocatable :: modules_used(:) s = s // \", modules_used=[\" do i = 1 , size ( source % modules_used ) s = s // '\"' // source % modules_used ( i )% s // '\"' if ( i < size ( source % modules_used )) s = s // \", \" end do s = s // \"]\" ! type(string_t), allocatable :: include_dependencies(:) s = s // \", include_dependencies=[\" do i = 1 , size ( source % include_dependencies ) s = s // '\"' // source % include_dependencies ( i )% s // '\"' if ( i < size ( source % include_dependencies )) s = s // \", \" end do s = s // \"]\" ! type(string_t), allocatable :: link_libraries(:) s = s // \", link_libraries=[\" do i = 1 , size ( source % link_libraries ) s = s // '\"' // source % link_libraries ( i )% s // '\"' if ( i < size ( source % link_libraries )) s = s // \", \" end do s = s // \"]\" ! integer(int64) :: digest s = s // \", digest=\" // str ( source % digest ) !end type srcfile_t s = s // \")\" end function info_srcfile function info_srcfile_short ( source ) result ( s ) ! Prints a shortened version of srcfile_t type ( srcfile_t ), intent ( in ) :: source character (:), allocatable :: s s = \"srcfile_t(\" s = s // 'file_name=\"' // source % file_name // '\"' s = s // \", ...)\" end function info_srcfile_short function info_model ( model ) result ( s ) type ( fpm_model_t ), intent ( in ) :: model character (:), allocatable :: s integer :: i !type :: fpm_model_t s = \"fpm_model_t(\" ! character(:), allocatable :: package_name s = s // 'package_name=\"' // model % package_name // '\"' ! type(srcfile_t), allocatable :: sources(:) s = s // \", packages=[\" do i = 1 , size ( model % packages ) s = s // info_package ( model % packages ( i )) if ( i < size ( model % packages )) s = s // \", \" end do s = s // \"]\" s = s // ', compiler=(' // debug ( model % compiler ) // ')' s = s // ', archiver=(' // debug ( model % archiver ) // ')' ! character(:), allocatable :: fortran_compile_flags s = s // ', fortran_compile_flags=\"' // model % fortran_compile_flags // '\"' s = s // ', c_compile_flags=\"' // model % c_compile_flags // '\"' s = s // ', cxx_compile_flags=\"' // model % cxx_compile_flags // '\"' s = s // ', link_flags=\"' // model % link_flags // '\"' s = s // ', build_prefix=\"' // model % build_prefix // '\"' ! type(string_t), allocatable :: link_libraries(:) s = s // \", link_libraries=[\" do i = 1 , size ( model % link_libraries ) s = s // '\"' // model % link_libraries ( i )% s // '\"' if ( i < size ( model % link_libraries )) s = s // \", \" end do s = s // \"]\" ! type(string_t), allocatable :: external_modules(:) s = s // \", external_modules=[\" do i = 1 , size ( model % external_modules ) s = s // '\"' // model % external_modules ( i )% s // '\"' if ( i < size ( model % external_modules )) s = s // \", \" end do s = s // \"]\" ! type(dependency_tree_t) :: deps ! TODO: print `dependency_tree_t` properly, which should become part of the ! model, not imported from another file s = s // \", deps=dependency_tree_t(...)\" ! Print module naming convention s = s // ', enforce_module_names=\"' // merge ( 'T' , 'F' , model % enforce_module_names ) // '\"' ! Print custom prefix if ( model % enforce_module_names . and . len_trim ( model % module_prefix ) > 0 ) & s = s // ', custom_prefix=\"' // model % module_prefix % s // '\"' !end type fpm_model_t s = s // \")\" end function info_model subroutine show_model ( model ) ! Prints a human readable representation of the Model type ( fpm_model_t ), intent ( in ) :: model print * , info_model ( model ) end subroutine show_model !> Return the character name of a scope flag function FPM_SCOPE_NAME ( flag ) result ( name ) integer , intent ( in ) :: flag character ( len = :), allocatable :: name select case ( flag ) case ( FPM_SCOPE_UNKNOWN ); name = \"FPM_SCOPE_UNKNOWN\" case ( FPM_SCOPE_LIB ); name = \"FPM_SCOPE_LIB\" case ( FPM_SCOPE_DEP ); name = \"FPM_SCOPE_DEP\" case ( FPM_SCOPE_APP ); name = \"FPM_SCOPE_APP\" case ( FPM_SCOPE_TEST ); name = \"FPM_SCOPE_TEST\" case ( FPM_SCOPE_EXAMPLE ); name = \"FPM_SCOPE_EXAMPLE\" case default ; name = \"INVALID\" end select end function FPM_SCOPE_NAME !> Parse git FPM_SCOPE identifier from a string integer function parse_scope ( name ) result ( scope ) character ( len =* ), intent ( in ) :: name character ( len = len ( name )) :: uppercase !> Make it Case insensitive uppercase = upper ( name ) select case ( trim ( uppercase )) case ( \"FPM_SCOPE_UNKNOWN\" ); scope = FPM_SCOPE_UNKNOWN case ( \"FPM_SCOPE_LIB\" ); scope = FPM_SCOPE_LIB case ( \"FPM_SCOPE_DEP\" ); scope = FPM_SCOPE_DEP case ( \"FPM_SCOPE_APP\" ); scope = FPM_SCOPE_APP case ( \"FPM_SCOPE_TEST\" ); scope = FPM_SCOPE_TEST case ( \"FPM_SCOPE_EXAMPLE\" ); scope = FPM_SCOPE_EXAMPLE case default ; scope = - 9999 end select end function parse_scope !> Return the character name of a unit flag function FPM_UNIT_NAME ( flag ) result ( name ) integer , intent ( in ) :: flag character ( len = :), allocatable :: name select case ( flag ) case ( FPM_UNIT_UNKNOWN ); name = \"FPM_UNIT_UNKNOWN\" case ( FPM_UNIT_PROGRAM ); name = \"FPM_UNIT_PROGRAM\" case ( FPM_UNIT_MODULE ); name = \"FPM_UNIT_MODULE\" case ( FPM_UNIT_SUBMODULE ); name = \"FPM_UNIT_SUBMODULE\" case ( FPM_UNIT_SUBPROGRAM ); name = \"FPM_UNIT_SUBPROGRAM\" case ( FPM_UNIT_CSOURCE ); name = \"FPM_UNIT_CSOURCE\" case ( FPM_UNIT_CPPSOURCE ); name = \"FPM_UNIT_CPPSOURCE\" case ( FPM_UNIT_CHEADER ); name = \"FPM_UNIT_CHEADER\" case default ; name = \"INVALID\" end select end function FPM_UNIT_NAME !> Parse git FPM_UNIT identifier from a string integer function parse_unit ( name ) result ( unit ) character ( len =* ), intent ( in ) :: name character ( len = len ( name )) :: uppercase !> Make it Case insensitive uppercase = upper ( name ) select case ( trim ( uppercase )) case ( \"FPM_UNIT_UNKNOWN\" ); unit = FPM_UNIT_UNKNOWN case ( \"FPM_UNIT_PROGRAM\" ); unit = FPM_UNIT_PROGRAM case ( \"FPM_UNIT_MODULE\" ); unit = FPM_UNIT_MODULE case ( \"FPM_UNIT_SUBMODULE\" ); unit = FPM_UNIT_SUBMODULE case ( \"FPM_UNIT_SUBPROGRAM\" ); unit = FPM_UNIT_SUBPROGRAM case ( \"FPM_UNIT_CSOURCE\" ); unit = FPM_UNIT_CSOURCE case ( \"FPM_UNIT_CPPSOURCE\" ); unit = FPM_UNIT_CPPSOURCE case ( \"FPM_UNIT_CHEADER\" ); unit = FPM_UNIT_CHEADER case default ; unit = - 9999 end select end function parse_unit !> Check that two source files are equal logical function srcfile_is_same ( this , that ) class ( srcfile_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that srcfile_is_same = . false . select type ( other => that ) type is ( srcfile_t ) if (. not .( this % file_name == other % file_name )) return if (. not .( this % exe_name == other % exe_name )) return if (. not .( this % unit_scope == other % unit_scope )) return if (. not .( this % modules_provided == other % modules_provided )) return if (. not .( this % unit_type == other % unit_type )) return if (. not .( this % parent_modules == other % parent_modules )) return if (. not .( this % modules_used == other % modules_used )) return if (. not .( this % include_dependencies == other % include_dependencies )) return if (. not .( this % link_libraries == other % link_libraries )) return if (. not .( this % digest == other % digest )) return class default ! Not the same type return end select !> All checks passed! srcfile_is_same = . true . end function srcfile_is_same !> Dump dependency to toml table subroutine srcfile_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( srcfile_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_string ( table , \"file-name\" , self % file_name , error , 'srcfile_t' ) if ( allocated ( error )) return call set_string ( table , \"exe-name\" , self % exe_name , error , 'srcfile_t' ) if ( allocated ( error )) return call set_value ( table , \"digest\" , self % digest , error , 'srcfile_t' ) if ( allocated ( error )) return ! unit_scope and unit_type are saved as strings so the output is independent ! of the internal representation call set_string ( table , \"unit-scope\" , FPM_SCOPE_NAME ( self % unit_scope ), error , 'srcfile_t' ) if ( allocated ( error )) return call set_string ( table , \"unit-type\" , FPM_UNIT_NAME ( self % unit_type ), error , 'srcfile_t' ) if ( allocated ( error )) return call set_list ( table , \"modules-provided\" , self % modules_provided , error ) if ( allocated ( error )) return call set_list ( table , \"parent-modules\" , self % parent_modules , error ) if ( allocated ( error )) return call set_list ( table , \"modules-used\" , self % modules_used , error ) if ( allocated ( error )) return call set_list ( table , \"include-dependencies\" , self % include_dependencies , error ) if ( allocated ( error )) return call set_list ( table , \"link-libraries\" , self % link_libraries , error ) if ( allocated ( error )) return end subroutine srcfile_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine srcfile_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( srcfile_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: flag integer :: ierr call get_value ( table , \"file-name\" , self % file_name ) call get_value ( table , \"exe-name\" , self % exe_name ) call get_value ( table , \"digest\" , self % digest , error , 'srcfile_t' ) if ( allocated ( error )) return ! unit_scope and unit_type are saved as strings so the output is independent ! of the internal representation call get_value ( table , \"unit-scope\" , flag ) if ( allocated ( flag )) self % unit_scope = parse_scope ( flag ) call get_value ( table , \"unit-type\" , flag ) if ( allocated ( flag )) self % unit_type = parse_unit ( flag ) call get_list ( table , \"modules-provided\" , self % modules_provided , error ) if ( allocated ( error )) return call get_list ( table , \"parent-modules\" , self % parent_modules , error ) if ( allocated ( error )) return call get_list ( table , \"modules-used\" , self % modules_used , error ) if ( allocated ( error )) return call get_list ( table , \"include-dependencies\" , self % include_dependencies , error ) if ( allocated ( error )) return call get_list ( table , \"link-libraries\" , self % link_libraries , error ) if ( allocated ( error )) return end subroutine srcfile_load_from_toml !> Check that two fortran feature objects are equal logical function fft_is_same ( this , that ) class ( fortran_features_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that fft_is_same = . false . select type ( other => that ) type is ( fortran_features_t ) if (. not .( this % implicit_typing . eqv . other % implicit_typing )) return if (. not .( this % implicit_external . eqv . other % implicit_external )) return if (. not .( this % source_form == other % source_form )) return class default ! Not the same type return end select !> All checks passed! fft_is_same = . true . end function fft_is_same !> Dump fortran features to toml table subroutine fft_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( fortran_features_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_value ( table , \"implicit-typing\" , self % implicit_typing , error , 'fortran_features_t' ) if ( allocated ( error )) return call set_value ( table , \"implicit-external\" , self % implicit_external , error , 'fortran_features_t' ) if ( allocated ( error )) return call set_string ( table , \"source-form\" , self % source_form , error , 'fortran_features_t' ) if ( allocated ( error )) return end subroutine fft_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine fft_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( fortran_features_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call get_value ( table , \"implicit-typing\" , self % implicit_typing , error , 'fortran_features_t' ) if ( allocated ( error )) return call get_value ( table , \"implicit-external\" , self % implicit_external , error , 'fortran_features_t' ) if ( allocated ( error )) return ! Return unallocated value if not present call get_value ( table , \"source-form\" , self % source_form ) end subroutine fft_load_from_toml !> Check that two package objects are equal logical function package_is_same ( this , that ) class ( package_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii package_is_same = . false . select type ( other => that ) type is ( package_t ) if (. not .( this % name == other % name )) return if (. not .( allocated ( this % sources ). eqv . allocated ( other % sources ))) return if ( allocated ( this % sources )) then if (. not .( size ( this % sources ) == size ( other % sources ))) return do ii = 1 , size ( this % sources ) if (. not .( this % sources ( ii ) == other % sources ( ii ))) return end do end if if (. not .( this % preprocess == other % preprocess )) return if (. not .( this % version == other % version )) return !> Module naming if (. not .( this % enforce_module_names . eqv . other % enforce_module_names )) return if (. not .( this % module_prefix == other % module_prefix )) return !> Fortran features if (. not .( this % features == other % features )) return class default ! Not the same type return end select !> All checks passed! package_is_same = . true . end function package_is_same !> Dump dependency to toml table subroutine package_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( package_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii type ( toml_table ), pointer :: ptr , this_source character ( 16 ) :: src_name call set_string ( table , \"name\" , self % name , error , 'package_t' ) if ( allocated ( error )) return call set_string ( table , \"version\" , self % version , error , 'package_t' ) if ( allocated ( error )) return call set_value ( table , \"module-naming\" , self % enforce_module_names , error , 'package_t' ) if ( allocated ( error )) return call set_string ( table , \"module-prefix\" , self % module_prefix , error , 'package_t' ) if ( allocated ( error )) return !> Create a preprocessor table call add_table ( table , \"preprocess\" , ptr , error , 'package_t' ) if ( allocated ( error )) return call self % preprocess % dump_to_toml ( ptr , error ) if ( allocated ( error )) return !> Create a fortran table call add_table ( table , \"fortran\" , ptr , error , 'package_t' ) if ( allocated ( error )) return call self % features % dump_to_toml ( ptr , error ) if ( allocated ( error )) return !> Create a sources table if ( allocated ( self % sources )) then call add_table ( table , \"sources\" , ptr , error , 'package_t' ) if ( allocated ( error )) return do ii = 1 , size ( self % sources ) write ( src_name , 1 ) ii call add_table ( ptr , trim ( src_name ), this_source , error , 'package_t[source]' ) if ( allocated ( error )) return call self % sources ( ii )% dump_to_toml ( this_source , error ) if ( allocated ( error )) return end do end if 1 format ( 'src_' , i0 ) end subroutine package_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine package_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( package_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii , jj type ( toml_key ), allocatable :: keys (:), src_keys (:) type ( toml_table ), pointer :: ptr_sources , ptr , ptr_fortran , ptr_preprocess type ( error_t ), allocatable :: new_error call get_value ( table , \"name\" , self % name ) call get_value ( table , \"version\" , self % version ) call get_value ( table , \"module-naming\" , self % enforce_module_names , error , 'package_t' ) if ( allocated ( error )) return ! Return unallocated value if not present call get_value ( table , \"module-prefix\" , self % module_prefix % s ) ! Sources call table % get_keys ( keys ) find_others : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"fortran\" ) call get_value ( table , keys ( ii ), ptr_fortran ) if (. not . associated ( ptr_fortran )) then call fatal_error ( error , 'package_t: error retrieving fortran table from TOML table' ) return end if call self % features % load_from_toml ( ptr_fortran , error ) if ( allocated ( error )) return case ( \"preprocess\" ) call get_value ( table , keys ( ii ), ptr_preprocess ) if (. not . associated ( ptr_preprocess )) then call fatal_error ( error , 'package_t: error retrieving preprocess table from TOML table' ) return end if call self % preprocess % load_from_toml ( ptr_preprocess , error ) if ( allocated ( error )) return case ( \"sources\" ) call get_value ( table , keys ( ii ), ptr_sources ) if (. not . associated ( ptr_sources )) then call fatal_error ( error , 'package_t: error retrieving sources table from TOML table' ) return end if !> Read all dependencies call ptr_sources % get_keys ( src_keys ) allocate ( self % sources ( size ( src_keys ))) do jj = 1 , size ( src_keys ) call get_value ( ptr_sources , src_keys ( jj ), ptr ) call self % sources ( jj )% load_from_toml ( ptr , error ) if ( allocated ( error )) return end do case default cycle find_others end select end do find_others end subroutine package_load_from_toml !> Check that two model objects are equal logical function model_is_same ( this , that ) class ( fpm_model_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that type ( fpm_model_t ), pointer :: other integer :: ii model_is_same = . false . select type ( other => that ) type is ( fpm_model_t ) if (. not .( this % package_name == other % package_name )) return if (. not .( allocated ( this % packages ). eqv . allocated ( other % packages ))) return if ( allocated ( this % packages )) then if (. not .( size ( this % packages ) == size ( other % packages ))) return do ii = 1 , size ( this % packages ) if (. not .( this % packages ( ii ) == other % packages ( ii ))) return end do end if if (. not .( this % compiler == other % compiler )) return if (. not .( this % archiver == other % archiver )) return if (. not .( this % fortran_compile_flags == other % fortran_compile_flags )) return if (. not .( this % c_compile_flags == other % c_compile_flags )) return if (. not .( this % cxx_compile_flags == other % cxx_compile_flags )) return if (. not .( this % link_flags == other % link_flags )) return if (. not .( this % build_prefix == other % build_prefix )) return if (. not .( this % include_dirs == other % include_dirs )) return if (. not .( this % link_libraries == other % link_libraries )) return if (. not .( this % external_modules == other % external_modules )) return if (. not .( this % deps == other % deps )) return if (. not .( this % include_tests . eqv . other % include_tests )) return if (. not .( this % enforce_module_names . eqv . other % enforce_module_names )) return if (. not .( this % module_prefix == other % module_prefix )) return class default ! Not the same type return end select !> All checks passed! model_is_same = . true . end function model_is_same !> Dump dependency to toml table subroutine model_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( fpm_model_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii type ( toml_table ), pointer :: ptr , ptr_pkg character ( 27 ) :: unnamed call set_string ( table , \"package-name\" , self % package_name , error , 'fpm_model_t' ) if ( allocated ( error )) return call add_table ( table , \"compiler\" , ptr , error , 'fpm_model_t' ) if ( allocated ( error )) return call self % compiler % dump_to_toml ( ptr , error ) if ( allocated ( error )) return call add_table ( table , \"archiver\" , ptr , error , 'fpm_model_t' ) if ( allocated ( error )) return call self % archiver % dump_to_toml ( ptr , error ) if ( allocated ( error )) return call set_string ( table , \"fortran-flags\" , self % fortran_compile_flags , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"c-flags\" , self % c_compile_flags , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"cxx-flags\" , self % cxx_compile_flags , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"link-flags\" , self % link_flags , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"build-prefix\" , self % build_prefix , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_list ( table , \"include-dirs\" , self % include_dirs , error ) if ( allocated ( error )) return call set_list ( table , \"link-libraries\" , self % link_libraries , error ) if ( allocated ( error )) return call set_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return call set_value ( table , \"include-tests\" , self % include_tests , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_value ( table , \"module-naming\" , self % enforce_module_names , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"module-prefix\" , self % module_prefix , error , 'fpm_model_t' ) if ( allocated ( error )) return call add_table ( table , \"deps\" , ptr , error , 'fpm_model_t' ) if ( allocated ( error )) return call self % deps % dump_to_toml ( ptr , error ) if ( allocated ( error )) return !> Array of packages (including the root package) if ( allocated ( self % packages )) then ! Create packages table call add_table ( table , \"packages\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , \"fpm_model_t cannot create dependency table \" ) return end if do ii = 1 , size ( self % packages ) associate ( pkg => self % packages ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , 'fpm_model_t[package]' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , 'fpm_model_t[package]' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if 1 format ( 'UNNAMED_PACKAGE_' , i0 ) end subroutine model_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine model_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( fpm_model_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: keys (:), pkg_keys (:) integer :: ierr , ii , jj type ( toml_table ), pointer :: ptr , ptr_pkg call table % get_keys ( keys ) call get_value ( table , \"package-name\" , self % package_name ) call get_value ( table , \"fortran-flags\" , self % fortran_compile_flags ) call get_value ( table , \"c-flags\" , self % c_compile_flags ) call get_value ( table , \"cxx-flags\" , self % cxx_compile_flags ) call get_value ( table , \"link-flags\" , self % link_flags ) call get_value ( table , \"build-prefix\" , self % build_prefix ) if ( allocated ( self % packages )) deallocate ( self % packages ) sub_deps : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"compiler\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'fpm_model_t: error retrieving compiler table' ) return end if call self % compiler % load_from_toml ( ptr , error ) if ( allocated ( error )) return case ( \"archiver\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'fpm_model_t: error retrieving archiver table' ) return end if call self % archiver % load_from_toml ( ptr , error ) if ( allocated ( error )) return case ( \"deps\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'fpm_model_t: error retrieving dependency tree table' ) return end if call self % deps % load_from_toml ( ptr , error ) if ( allocated ( error )) return case ( \"packages\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'fpm_model_t: error retrieving packages table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % packages ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % packages ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case default cycle sub_deps end select end do sub_deps call get_list ( table , \"include-dirs\" , self % include_dirs , error ) if ( allocated ( error )) return call get_list ( table , \"link-libraries\" , self % link_libraries , error ) if ( allocated ( error )) return call get_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return call get_value ( table , \"include-tests\" , self % include_tests , error , 'fpm_model_t' ) if ( allocated ( error )) return call get_value ( table , \"module-naming\" , self % enforce_module_names , error , 'fpm_model_t' ) if ( allocated ( error )) return call get_value ( table , \"module-prefix\" , self % module_prefix % s ) end subroutine model_load_from_toml end module fpm_model","tags":"","loc":"sourcefile/fpm_model.f90.html"},{"title":"fpm_sources.f90 – Fortran-lang/fpm","text":"Source Code !># Discovery of sources !> !> This module implements subroutines for building a list of !> `[[srcfile_t]]` objects by looking for source files in the filesystem. !> module fpm_sources use fpm_error , only : error_t use fpm_model , only : srcfile_t , FPM_UNIT_PROGRAM use fpm_filesystem , only : basename , canon_path , dirname , join_path , list_files , is_hidden_file use fpm_environment , only : get_os_type , OS_WINDOWS use fpm_strings , only : lower , str_ends_with , string_t , operator (. in .) use fpm_source_parsing , only : parse_f_source , parse_c_source use fpm_manifest_executable , only : executable_config_t implicit none private public :: add_sources_from_dir , add_executable_sources public :: get_exe_name_with_suffix character ( 4 ), parameter :: fortran_suffixes ( 2 ) = [ \".f90\" , & \".f \" ] character ( 4 ), parameter :: c_suffixes ( 4 ) = [ \".c \" , \".h \" , \".cpp\" , \".hpp\" ] contains !> Wrapper to source parsing routines. !> Selects parsing routine based on source file name extension function parse_source ( source_file_path , custom_f_ext , error ) result ( source ) character ( * ), intent ( in ) :: source_file_path type ( string_t ), optional , intent ( in ) :: custom_f_ext (:) type ( error_t ), allocatable , intent ( out ) :: error type ( srcfile_t ) :: source type ( string_t ), allocatable :: f_ext (:) call list_fortran_suffixes ( f_ext , custom_f_ext ) if ( str_ends_with ( lower ( source_file_path ), f_ext )) then source = parse_f_source ( source_file_path , error ) if ( source % unit_type == FPM_UNIT_PROGRAM ) then source % exe_name = basename ( source_file_path , suffix = . false .) end if else if ( str_ends_with ( lower ( source_file_path ), c_suffixes )) then source = parse_c_source ( source_file_path , error ) endif if ( allocated ( error )) then return end if end function parse_source !> List fortran suffixes, including optional ones subroutine list_fortran_suffixes ( suffixes , with_f_ext ) type ( string_t ), allocatable , intent ( out ) :: suffixes (:) !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) integer :: ndefault , nuser , i ndefault = size ( fortran_suffixes ) nuser = 0 ; if ( present ( with_f_ext )) nuser = size ( with_f_ext ) allocate ( suffixes ( ndefault + nuser )) do i = 1 , ndefault suffixes ( i ) = string_t ( fortran_suffixes ( i )) end do if ( present ( with_f_ext )) then do i = 1 , nuser suffixes ( ndefault + i ) = string_t ( with_f_ext ( i )% s ) end do endif end subroutine list_fortran_suffixes !> Add to `sources` by looking for source files in `directory` subroutine add_sources_from_dir ( sources , directory , scope , with_executables , with_f_ext , recurse , error ) !> List of `[[srcfile_t]]` objects to append to. Allocated if not allocated type ( srcfile_t ), allocatable , intent ( inout ), target :: sources (:) !> Directory in which to search for source files character ( * ), intent ( in ) :: directory !> Scope to apply to the discovered sources, see [[fpm_model]] for enumeration integer , intent ( in ) :: scope !> Executable sources (fortran `program`s) are ignored unless `with_executables=.true.` logical , intent ( in ), optional :: with_executables !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) !> Whether to recursively search subdirectories, default is `.true.` logical , intent ( in ), optional :: recurse !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i logical , allocatable :: is_source (:), exclude_source (:) logical :: recurse_ type ( string_t ), allocatable :: file_names (:) type ( string_t ), allocatable :: src_file_names (:), f_ext (:) type ( string_t ), allocatable :: existing_src_files (:) type ( srcfile_t ), allocatable :: dir_sources (:) recurse_ = . true . if ( present ( recurse )) recurse_ = recurse ! Scan directory for sources call list_files ( directory , file_names , recurse = recurse_ ) if ( allocated ( sources )) then allocate ( existing_src_files ( size ( sources ))) do i = 1 , size ( sources ) existing_src_files ( i )% s = canon_path ( sources ( i )% file_name ) end do else allocate ( existing_src_files ( 0 )) end if ! Get legal fortran suffixes call list_fortran_suffixes ( f_ext , with_f_ext ) is_source = [(. not .( is_hidden_file ( basename ( file_names ( i )% s ))) . and . & . not .( canon_path ( file_names ( i )% s ) . in . existing_src_files ) . and . & ( str_ends_with ( lower ( file_names ( i )% s ), f_ext ) . or . & str_ends_with ( lower ( file_names ( i )% s ), c_suffixes ) ), i = 1 , size ( file_names ))] src_file_names = pack ( file_names , is_source ) allocate ( dir_sources ( size ( src_file_names ))) allocate ( exclude_source ( size ( src_file_names ))) do i = 1 , size ( src_file_names ) dir_sources ( i ) = parse_source ( src_file_names ( i )% s , with_f_ext , error ) if ( allocated ( error )) return dir_sources ( i )% unit_scope = scope allocate ( dir_sources ( i )% link_libraries ( 0 )) ! Exclude executables unless specified otherwise exclude_source ( i ) = ( dir_sources ( i )% unit_type == FPM_UNIT_PROGRAM ) if ( dir_sources ( i )% unit_type == FPM_UNIT_PROGRAM . and . & & present ( with_executables )) then if ( with_executables ) then exclude_source ( i ) = . false . end if end if end do if (. not . allocated ( sources )) then sources = pack ( dir_sources ,. not . exclude_source ) else sources = [ sources , pack ( dir_sources ,. not . exclude_source )] end if end subroutine add_sources_from_dir !> Add to `sources` using the executable and test entries in the manifest and !> applies any executable-specific overrides such as `executable%name`. !> Adds all sources (including modules) from each `executable%source_dir` subroutine add_executable_sources ( sources , executables , scope , auto_discover , with_f_ext , error ) !> List of `[[srcfile_t]]` objects to append to. Allocated if not allocated type ( srcfile_t ), allocatable , intent ( inout ), target :: sources (:) !> List of `[[executable_config_t]]` entries from manifest class ( executable_config_t ), intent ( in ) :: executables (:) !> Scope to apply to the discovered sources: either `FPM_SCOPE_APP` or `FPM_SCOPE_TEST`, see [[fpm_model]] integer , intent ( in ) :: scope !> If `.false.` only executables and tests specified in the manifest are added to `sources` logical , intent ( in ) :: auto_discover !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j type ( string_t ), allocatable :: exe_dirs (:) type ( srcfile_t ) :: exe_source call get_executable_source_dirs ( exe_dirs , executables ) do i = 1 , size ( exe_dirs ) call add_sources_from_dir ( sources , exe_dirs ( i )% s , scope , & with_executables = auto_discover , with_f_ext = with_f_ext , recurse = . false ., error = error ) if ( allocated ( error )) then return end if end do exe_loop : do i = 1 , size ( executables ) ! Check if executable already discovered automatically ! and apply any overrides do j = 1 , size ( sources ) !> Compare lowercase strings to allow auto-discovery of pre-processed extensions if ( lower ( basename ( sources ( j )% file_name , suffix = . true .)) == lower ( executables ( i )% main ) . and .& canon_path ( dirname ( sources ( j )% file_name )) == & canon_path ( executables ( i )% source_dir ) ) then sources ( j )% exe_name = executables ( i )% name if ( allocated ( executables ( i )% link )) then sources ( j )% link_libraries = executables ( i )% link end if sources ( j )% unit_type = FPM_UNIT_PROGRAM cycle exe_loop end if end do ! Add if not already discovered (auto_discovery off) associate ( exe => executables ( i )) exe_source = parse_source ( join_path ( exe % source_dir , exe % main ), with_f_ext , error ) exe_source % exe_name = exe % name if ( allocated ( exe % link )) then exe_source % link_libraries = exe % link end if exe_source % unit_type = FPM_UNIT_PROGRAM exe_source % unit_scope = scope end associate if ( allocated ( error )) return if (. not . allocated ( sources )) then sources = [ exe_source ] else sources = [ sources , exe_source ] end if end do exe_loop end subroutine add_executable_sources !> Build a list of unique source directories !> from executables specified in manifest subroutine get_executable_source_dirs ( exe_dirs , executables ) type ( string_t ), allocatable , intent ( inout ) :: exe_dirs (:) class ( executable_config_t ), intent ( in ) :: executables (:) type ( string_t ) :: dirs_temp ( size ( executables )) integer :: i , n n = 0 do i = 1 , size ( executables ) dirs_temp ( i )% s = ' ' enddo do i = 1 , size ( executables ) if (. not .( executables ( i )% source_dir . in . dirs_temp )) then n = n + 1 dirs_temp ( n )% s = executables ( i )% source_dir end if end do if (. not . allocated ( exe_dirs )) then exe_dirs = dirs_temp ( 1 : n ) else exe_dirs = [ exe_dirs , dirs_temp ( 1 : n )] end if end subroutine get_executable_source_dirs !> Build an executable name with suffix. Safe routine that always returns an allocated string function get_exe_name_with_suffix ( source ) result ( suffixed ) type ( srcfile_t ), intent ( in ) :: source character ( len = :), allocatable :: suffixed if ( allocated ( source % exe_name )) then if ( get_os_type () == OS_WINDOWS ) then suffixed = source % exe_name // '.exe' else suffixed = source % exe_name end if else suffixed = \"\" endif end function get_exe_name_with_suffix end module fpm_sources","tags":"","loc":"sourcefile/fpm_sources.f90.html"},{"title":"library.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for libraries. !> !> A library table can currently have the following fields !> !>```toml !>[library] !>source-dir = \"path\" !>include-dir = [\"path1\",\"path2\"] !>build-script = \"file\" !>``` module fpm_manifest_library use fpm_error , only : error_t , syntax_error use fpm_strings , only : string_t , string_cat , operator ( == ) use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list , serializable_t , set_value , & set_list , set_string , get_value , get_list implicit none private public :: library_config_t , new_library !> Configuration meta data for a library type , extends ( serializable_t ) :: library_config_t !> Source path prefix character ( len = :), allocatable :: source_dir !> Include path prefix type ( string_t ), allocatable :: include_dir (:) !> Alternative build script to be invoked character ( len = :), allocatable :: build_script contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => library_is_same procedure :: dump_to_toml procedure :: load_from_toml end type library_config_t character ( * ), parameter , private :: class_name = 'library_config_t' contains !> Construct a new library configuration from a TOML data structure subroutine new_library ( self , table , error ) !> Instance of the library configuration type ( library_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"source-dir\" , self % source_dir , \"src\" ) call get_value ( table , \"build-script\" , self % build_script ) call get_list ( table , \"include-dir\" , self % include_dir , error ) if ( allocated ( error )) return ! Set default value of include-dir if not found in manifest if (. not . allocated ( self % include_dir )) then self % include_dir = [ string_t ( \"include\" )] end if end subroutine new_library !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_keys ( list ) ! table can be empty if ( size ( list ) < 1 ) return do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in library\" ) exit case ( \"source-dir\" , \"include-dir\" , \"build-script\" ) continue end select end do end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the library configuration class ( library_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Library target\" if ( allocated ( self % source_dir )) then write ( unit , fmt ) \"- source directory\" , self % source_dir end if if ( allocated ( self % include_dir )) then write ( unit , fmt ) \"- include directory\" , string_cat ( self % include_dir , \",\" ) end if if ( allocated ( self % build_script )) then write ( unit , fmt ) \"- custom build\" , self % build_script end if end subroutine info logical function library_is_same ( this , that ) class ( library_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that library_is_same = . false . select type ( other => that ) type is ( library_config_t ) if (. not . this % include_dir == other % include_dir ) return if (. not . allocated ( this % source_dir ). eqv . allocated ( other % source_dir )) return if (. not . this % source_dir == other % source_dir ) return if (. not . allocated ( this % build_script ). eqv . allocated ( other % build_script )) return if (. not . this % build_script == other % build_script ) return class default ! Not the same type return end select !> All checks passed! library_is_same = . true . end function library_is_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( library_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_string ( table , \"source-dir\" , self % source_dir , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"build-script\" , self % build_script , error , class_name ) if ( allocated ( error )) return call set_list ( table , \"include-dir\" , self % include_dir , error ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( library_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"source-dir\" , self % source_dir ) if ( allocated ( error )) return call get_value ( table , \"build-script\" , self % build_script ) if ( allocated ( error )) return call get_list ( table , \"include-dir\" , self % include_dir , error ) end subroutine load_from_toml end module fpm_manifest_library","tags":"","loc":"sourcefile/library.f90.html"},{"title":"fpm_source_parsing.f90 – Fortran-lang/fpm","text":"Source Code !># Parsing of package source files !> !> This module exposes two functions, `[[parse_f_source]]` and `[[parse_c_source]]`, !> which perform a rudimentary parsing of fortran and c source files !> in order to extract information required for module dependency tracking. !> !> Both functions additionally calculate and store a file digest (hash) which !> is used by the backend ([[fpm_backend]]) to skip compilation of unmodified sources. !> !> Both functions return an instance of the [[srcfile_t]] type. !> !> For more information, please read the documentation for each function: !> !> - `[[parse_f_source]]` !> - `[[parse_c_source]]` !> module fpm_source_parsing use fpm_error , only : error_t , file_parse_error , fatal_error , file_not_found_error use fpm_strings , only : string_t , string_cat , len_trim , split , lower , str_ends_with , fnv_1a , is_fortran_name use fpm_model , only : srcfile_t , & FPM_UNIT_UNKNOWN , FPM_UNIT_PROGRAM , FPM_UNIT_MODULE , & FPM_UNIT_SUBMODULE , FPM_UNIT_SUBPROGRAM , & FPM_UNIT_CSOURCE , FPM_UNIT_CHEADER , FPM_SCOPE_UNKNOWN , & FPM_SCOPE_LIB , FPM_SCOPE_DEP , FPM_SCOPE_APP , FPM_SCOPE_TEST , & FPM_UNIT_CPPSOURCE use fpm_filesystem , only : read_lines , read_lines_expanded , exists implicit none private public :: parse_f_source , parse_c_source , parse_use_statement contains !> Parsing of free-form fortran source files !> !> The following statements are recognised and parsed: !> !> - `Module`/`submodule`/`program` declaration !> - Module `use` statement !> - `include` statement !> !> @note Intrinsic modules used by sources are not listed in !> the `modules_used` field of source objects. !> !> @note Submodules are treated as normal modules which `use` their !> corresponding parent modules. !> !>### Parsing limitations !> !> __Statements must not continued onto another line !> except for an `only:` list in the `use` statement.__ !> !> This is supported: !> !>```fortran !> use my_module, only: & !> my_var, my_function, my_subroutine !>``` !> !> This is __NOT supported:__ !> !>```fortran !> use & !> my_module !>``` !> function parse_f_source ( f_filename , error ) result ( f_source ) character ( * ), intent ( in ) :: f_filename type ( srcfile_t ) :: f_source type ( error_t ), allocatable , intent ( out ) :: error logical :: inside_module , inside_interface , using , intrinsic_module integer :: stat integer :: fh , n_use , n_include , n_mod , n_parent , i , j , ic , pass type ( string_t ), allocatable :: file_lines (:), file_lines_lower (:) character (:), allocatable :: temp_string , mod_name , string_parts (:) if (. not . exists ( f_filename )) then call file_not_found_error ( error , f_filename ) return end if f_source % file_name = f_filename file_lines = read_lines_expanded ( f_filename ) ! for efficiency in parsing make a lowercase left-adjusted copy of the file ! Need a copy because INCLUDE (and #include) file arguments are case-sensitive file_lines_lower = file_lines do i = 1 , size ( file_lines_lower ) file_lines_lower ( i )% s = adjustl ( lower ( file_lines_lower ( i )% s )) enddo ! fnv_1a can only be applied to non-zero-length arrays if ( len_trim ( file_lines_lower ) > 0 ) f_source % digest = fnv_1a ( file_lines ) do pass = 1 , 2 n_use = 0 n_include = 0 n_mod = 0 n_parent = 0 inside_module = . false . inside_interface = . false . file_loop : do i = 1 , size ( file_lines_lower ) ! Skip comment lines and preprocessor directives if ( index ( file_lines_lower ( i )% s , '!' ) == 1 . or . & index ( file_lines_lower ( i )% s , '#' ) == 1 . or . & len_trim ( file_lines_lower ( i )% s ) < 1 ) then cycle end if ! Detect exported C-API via bind(C) if (. not . inside_interface . and . & parse_subsequence ( file_lines_lower ( i )% s , 'bind' , '(' , 'c' )) then do j = i , 1 , - 1 if ( index ( file_lines_lower ( j )% s , 'function' ) > 0 . or . & index ( file_lines_lower ( j )% s , 'subroutine' ) > 0 ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM exit end if if ( j > 1 ) then ic = index ( file_lines_lower ( j - 1 )% s , '!' ) if ( ic < 1 ) then ic = len ( file_lines_lower ( j - 1 )% s ) end if temp_string = trim ( file_lines_lower ( j - 1 )% s ( 1 : ic )) if ( index ( temp_string , '&' ) /= len ( temp_string )) then exit end if end if end do end if ! Skip lines that are continued: not statements if ( i > 1 ) then ic = index ( file_lines_lower ( i - 1 )% s , '!' ) if ( ic < 1 ) then ic = len ( file_lines_lower ( i - 1 )% s ) end if temp_string = trim ( file_lines_lower ( i - 1 )% s ( 1 : ic )) if ( len ( temp_string ) > 0 . and . index ( temp_string , '&' ) == len ( temp_string )) then cycle end if end if ! Detect beginning of interface block if ( index ( file_lines_lower ( i )% s , 'interface' ) == 1 & . or . parse_sequence ( file_lines_lower ( i )% s , 'abstract' , 'interface' )) then inside_interface = . true . cycle end if ! Detect end of interface block if ( parse_sequence ( file_lines_lower ( i )% s , 'end' , 'interface' )) then inside_interface = . false . cycle end if ! Process 'USE' statements call parse_use_statement ( f_filename , i , file_lines_lower ( i )% s , using , intrinsic_module , mod_name , error ) if ( allocated ( error )) return if ( using ) then ! Not a valid module name? if (. not . is_fortran_name ( mod_name )) cycle ! Valid intrinsic module: not a dependency if ( intrinsic_module ) cycle n_use = n_use + 1 if ( pass == 2 ) f_source % modules_used ( n_use )% s = mod_name cycle endif ! Process 'INCLUDE' statements ic = index ( file_lines_lower ( i )% s , 'include' ) if ( ic == 1 ) then ic = index ( lower ( file_lines ( i )% s ), 'include' ) if ( index ( adjustl ( file_lines ( i )% s ( ic + 7 :)), '\"' ) == 1 . or . & index ( adjustl ( file_lines ( i )% s ( ic + 7 :)), \"'\" ) == 1 ) then n_include = n_include + 1 if ( pass == 2 ) then f_source % include_dependencies ( n_include )% s = & & split_n ( file_lines ( i )% s , n = 2 , delims = \"'\" // '\"' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find include file name' , i , & file_lines ( i )% s ) return end if end if cycle end if end if ! Extract name of module if is module if ( index ( file_lines_lower ( i )% s , 'module ' ) == 1 ) then ! Remove any trailing comments ic = index ( file_lines_lower ( i )% s , '!' ) - 1 if ( ic < 1 ) then ic = len ( file_lines_lower ( i )% s ) end if temp_string = trim ( file_lines_lower ( i )% s ( 1 : ic )) ! R1405 module-stmt := \"MODULE\" module-name ! module-stmt has two space-delimited parts only ! (no line continuations) call split ( temp_string , string_parts , ' ' ) if ( size ( string_parts ) /= 2 ) then cycle end if mod_name = trim ( adjustl ( string_parts ( 2 ))) if ( scan ( mod_name , '=(&' ) > 0 ) then ! Ignore these cases: ! module & ! module =* ! module (i) cycle end if if (. not . is_fortran_name ( mod_name )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for module' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , mod_name )) return end if n_mod = n_mod + 1 if ( pass == 2 ) then f_source % modules_provided ( n_mod ) = string_t ( mod_name ) end if if ( f_source % unit_type == FPM_UNIT_UNKNOWN ) then f_source % unit_type = FPM_UNIT_MODULE end if if (. not . inside_module ) then inside_module = . true . else ! Must have missed an end module statement (can't assume a pure module) if ( f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if end if cycle end if ! Extract name of submodule if is submodule if ( index ( file_lines_lower ( i )% s , 'submodule' ) == 1 ) then mod_name = split_n ( file_lines_lower ( i )% s , n = 3 , delims = '()' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to get submodule name' , i , & file_lines_lower ( i )% s ) return end if if (. not . is_fortran_name ( mod_name )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for submodule' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , mod_name )) return end if n_mod = n_mod + 1 temp_string = split_n ( file_lines_lower ( i )% s , n = 2 , delims = '()' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to get submodule ancestry' , i , & file_lines_lower ( i )% s ) return end if if ( f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBMODULE end if n_use = n_use + 1 inside_module = . true . n_parent = n_parent + 1 if ( pass == 2 ) then if ( index ( temp_string , ':' ) > 0 ) then temp_string = temp_string ( index ( temp_string , ':' ) + 1 :) end if if (. not . is_fortran_name ( temp_string )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for submodule parent' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , temp_string )) return end if f_source % modules_used ( n_use )% s = temp_string f_source % parent_modules ( n_parent )% s = temp_string f_source % modules_provided ( n_mod )% s = mod_name end if cycle end if ! Detect if contains a program ! (no modules allowed after program def) if ( index ( file_lines_lower ( i )% s , 'program ' ) == 1 ) then temp_string = split_n ( file_lines_lower ( i )% s , n = 2 , delims = ' ' , stat = stat ) if ( stat == 0 ) then if ( scan ( temp_string , '=(' ) > 0 ) then ! Ignore: ! program =* ! program (i) =* cycle end if end if f_source % unit_type = FPM_UNIT_PROGRAM cycle end if ! Parse end module statement ! (to check for code outside of modules) if ( parse_sequence ( file_lines_lower ( i )% s , 'end' , 'module' ) . or . & parse_sequence ( file_lines_lower ( i )% s , 'end' , 'submodule' )) then inside_module = . false . cycle end if ! Any statements not yet parsed are assumed to be other code statements if (. not . inside_module . and . f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if end do file_loop ! If unable to parse end of module statement, then can't assume pure module ! (there could be non-module subprograms present) if ( inside_module . and . f_source % unit_type == FPM_UNIT_MODULE ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if if ( pass == 1 ) then allocate ( f_source % modules_used ( n_use )) allocate ( f_source % include_dependencies ( n_include )) allocate ( f_source % modules_provided ( n_mod )) allocate ( f_source % parent_modules ( n_parent )) end if end do end function parse_f_source !> Parsing of c, cpp source files !> !> The following statements are recognised and parsed: !> !> - `#include` preprocessor statement !> function parse_c_source ( c_filename , error ) result ( c_source ) character ( * ), intent ( in ) :: c_filename type ( srcfile_t ) :: c_source type ( error_t ), allocatable , intent ( out ) :: error integer :: fh , n_include , i , pass , stat type ( string_t ), allocatable :: file_lines (:) c_source % file_name = c_filename if ( str_ends_with ( lower ( c_filename ), \".c\" )) then c_source % unit_type = FPM_UNIT_CSOURCE else if ( str_ends_with ( lower ( c_filename ), \".h\" )) then c_source % unit_type = FPM_UNIT_CHEADER else if ( str_ends_with ( lower ( c_filename ), \".cpp\" )) then c_source % unit_type = FPM_UNIT_CPPSOURCE end if allocate ( c_source % modules_used ( 0 )) allocate ( c_source % modules_provided ( 0 )) allocate ( c_source % parent_modules ( 0 )) file_lines = read_lines ( c_filename ) ! Ignore empty files, returned as FPM_UNIT_UNKNOWN if ( len_trim ( file_lines ) < 1 ) then c_source % unit_type = FPM_UNIT_UNKNOWN return end if c_source % digest = fnv_1a ( file_lines ) do pass = 1 , 2 n_include = 0 file_loop : do i = 1 , size ( file_lines ) ! Process 'INCLUDE' statements if ( index ( adjustl ( lower ( file_lines ( i )% s )), '#include' ) == 1 . and . & index ( file_lines ( i )% s , '\"' ) > 0 ) then n_include = n_include + 1 if ( pass == 2 ) then c_source % include_dependencies ( n_include )% s = & & split_n ( file_lines ( i )% s , n = 2 , delims = '\"' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , c_filename , & 'unable to get c include file' , i , & file_lines ( i )% s , index ( file_lines ( i )% s , '\"' )) return end if end if end if end do file_loop if ( pass == 1 ) then allocate ( c_source % include_dependencies ( n_include )) end if end do end function parse_c_source !> Split a string on one or more delimeters !> and return the nth substring if it exists !> !> n=0 will return the last item !> n=-1 will return the penultimate item etc. !> !> stat = 1 on return if the index !> is not found !> function split_n ( string , delims , n , stat ) result ( substring ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: delims integer , intent ( in ) :: n integer , intent ( out ) :: stat character (:), allocatable :: substring integer :: i character (:), allocatable :: string_parts (:) call split ( string , string_parts , delims ) if ( n < 1 ) then i = size ( string_parts ) + n if ( i < 1 ) then allocate ( character ( len = 0 ) :: substring ) ! ifort bus error otherwise stat = 1 return end if else i = n end if if ( i > size ( string_parts )) then allocate ( character ( len = 0 ) :: substring ) ! ifort bus error otherwise stat = 1 return end if substring = trim ( adjustl ( string_parts ( i ))) stat = 0 end function split_n !> Parse a subsequence of blank-separated tokens within a string !> (see parse_sequence) function parse_subsequence ( string , t1 , t2 , t3 , t4 ) result ( found ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: t1 character ( * ), intent ( in ), optional :: t2 , t3 , t4 logical :: found integer :: offset , i found = . false . offset = 1 do i = index ( string ( offset :), t1 ) if ( i == 0 ) return offset = offset + i - 1 found = parse_sequence ( string ( offset :), t1 , t2 , t3 , t4 ) if ( found ) return offset = offset + len ( t1 ) if ( offset > len ( string )) return end do end function parse_subsequence !> Helper utility to parse sequences of tokens !> that may be optionally separated by zero or more spaces function parse_sequence ( string , t1 , t2 , t3 , t4 ) result ( found ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: t1 character ( * ), intent ( in ), optional :: t2 , t3 , t4 logical :: found integer :: post , n , incr , pos , token_n logical :: match n = len ( string ) found = . false . pos = 1 do token_n = 1 , 4 do while ( pos <= n ) if ( string ( pos : pos ) /= ' ' ) then exit end if pos = pos + 1 end do select case ( token_n ) case ( 1 ) incr = len ( t1 ) if ( pos + incr - 1 > n ) return match = string ( pos : pos + incr - 1 ) == t1 case ( 2 ) if (. not . present ( t2 )) exit incr = len ( t2 ) if ( pos + incr - 1 > n ) return match = string ( pos : pos + incr - 1 ) == t2 case ( 3 ) if (. not . present ( t3 )) exit incr = len ( t3 ) if ( pos + incr - 1 > n ) return match = string ( pos : pos + incr - 1 ) == t3 case ( 4 ) if (. not . present ( t4 )) exit incr = len ( t4 ) if ( pos + incr - 1 > n ) return match = string ( pos : pos + incr - 1 ) == t4 case default exit end select if (. not . match ) then return end if pos = pos + incr end do found = . true . end function parse_sequence ! USE [, intrinsic] :: module_name [, only: only_list] ! USE [, non_intrinsic] :: module_name [, only: only_list] subroutine parse_use_statement ( f_filename , i , line , use_stmt , is_intrinsic , module_name , error ) !> Current file name and line number (for error messaging) character ( * ), intent ( in ) :: f_filename integer , intent ( in ) :: i !> The line being parsed. MUST BE preprocessed with trim(adjustl() character ( * ), intent ( in ) :: line !> Does this line contain a `use` statement? logical , intent ( out ) :: use_stmt !> Is the module in this statement intrinsic? logical , intent ( out ) :: is_intrinsic !> used module name character (:), allocatable , intent ( out ) :: module_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( 15 ), parameter :: INTRINSIC_NAMES ( * ) = & [ 'iso_c_binding ' , & 'iso_fortran_env' , & 'ieee_arithmetic' , & 'ieee_exceptions' , & 'ieee_features ' , & 'omp_lib ' ] character ( len = :), allocatable :: temp_string integer :: colons , intr , nonintr , j , stat logical :: has_intrinsic_name use_stmt = . false . is_intrinsic = . false . if ( len_trim ( line ) <= 0 ) return ! Quick check that the line is preprocessed if ( line ( 1 : 1 ) == ' ' ) then call fatal_error ( error , 'internal_error: source file line is not trim(adjustl()) on input to parse_use_statement' ) return end if ! 'use' should be the first string in the adjustl line use_stmt = index ( line , 'use ' ) == 1 . or . index ( line , 'use::' ) == 1 . or . index ( line , 'use,' ) == 1 if (. not . use_stmt ) return colons = index ( line , '::' ) nonintr = 0 intr = 0 have_colons : if ( colons > 3 ) then ! there may be an intrinsic/non-intrinsic spec nonintr = index ( line ( 1 : colons - 1 ), 'non_intrinsic' ) if ( nonintr == 0 ) intr = index ( line ( 1 : colons - 1 ), 'intrinsic' ) temp_string = split_n ( line , delims = ':' , n = 2 , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line , colons ) return end if module_name = split_n ( temp_string , delims = ' ,' , n = 1 , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line ) return end if else module_name = split_n ( line , n = 2 , delims = ' ,' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line ) return end if end if have_colons ! If declared intrinsic, check that it is true has_intrinsic_name = any ([( index ( module_name , trim ( INTRINSIC_NAMES ( j ))) > 0 , & j = 1 , size ( INTRINSIC_NAMES ))]) if ( intr > 0 . and . . not . has_intrinsic_name ) then ! An intrinsic module was not found. Its name could be in the next line, ! in which case, we just skip this check. The compiler will do the job if the name is invalid. ! Module name was not read: it's in the next line if ( index ( module_name , '&' ) <= 0 ) then call file_parse_error ( error , f_filename , & 'module ' // module_name // ' is declared intrinsic but it is not ' , i , & line ) return endif endif ! Should we treat this as an intrinsic module is_intrinsic = nonintr == 0 . and . & ! not declared non-intrinsic ( intr > 0 . or . has_intrinsic_name ) end subroutine parse_use_statement end module fpm_source_parsing","tags":"","loc":"sourcefile/fpm_source_parsing.f90.html"},{"title":"error.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of basic error handling. module fpm_error use , intrinsic :: iso_fortran_env , only : stdin => input_unit , stdout => output_unit , stderr => error_unit use fpm_strings , only : is_fortran_name , to_fortran_name implicit none private public :: error_t public :: fatal_error , syntax_error , file_not_found_error public :: file_parse_error public :: bad_name_error public :: fpm_stop !> Data type defining an error type :: error_t !> Error message character ( len = :), allocatable :: message end type error_t contains !> Generic fatal runtime error subroutine fatal_error ( error , message ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message character ( len =* ), intent ( in ) :: message allocate ( error ) error % message = message end subroutine fatal_error subroutine syntax_error ( error , message ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message character ( len =* ), intent ( in ) :: message allocate ( error ) error % message = message end subroutine syntax_error function bad_name_error ( error , label , name ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message label to add to message character ( len =* ), intent ( in ) :: label !> name value to check character ( len =* ), intent ( in ) :: name logical :: bad_name_error if (. not . is_fortran_name ( to_fortran_name ( name ))) then bad_name_error = . true . allocate ( error ) error % message = 'manifest file syntax error: ' // label // ' name must be composed only of & &alphanumerics, \"-\" and \"_\" and start with a letter ::' // name else bad_name_error = . false . endif end function bad_name_error !> Error created when a file is missing or not found subroutine file_not_found_error ( error , file_name ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Name of the missing file character ( len =* ), intent ( in ) :: file_name allocate ( error ) error % message = \"'\" // file_name // \"' could not be found, check if the file exists\" end subroutine file_not_found_error !> Error created when file parsing fails subroutine file_parse_error ( error , file_name , message , line_num , & line_string , line_col ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Name of file character ( len =* ), intent ( in ) :: file_name !> Parse error message character ( len =* ), intent ( in ) :: message !> Line number of parse error integer , intent ( in ), optional :: line_num !> Line context string character ( len =* ), intent ( in ), optional :: line_string !> Line context column integer , intent ( in ), optional :: line_col character ( 50 ) :: temp_string allocate ( error ) error % message = 'Parse error: ' // message // new_line ( 'a' ) error % message = error % message // file_name if ( present ( line_num )) then write ( temp_string , '(I0)' ) line_num error % message = error % message // ':' // trim ( temp_string ) end if if ( present ( line_col )) then if ( line_col > 0 ) then write ( temp_string , '(I0)' ) line_col error % message = error % message // ':' // trim ( temp_string ) end if end if if ( present ( line_string )) then error % message = error % message // new_line ( 'a' ) error % message = error % message // ' | ' // line_string if ( present ( line_col )) then if ( line_col > 0 ) then error % message = error % message // new_line ( 'a' ) error % message = error % message // ' | ' // repeat ( ' ' , line_col - 1 ) // '^' end if end if end if end subroutine file_parse_error subroutine fpm_stop ( value , message ) ! TODO: if verbose mode, call ERROR STOP instead of STOP ! TODO: if M_escape is used, add color ! to work with older compilers might need a case statement for values !> value to use on STOP integer , intent ( in ) :: value !> Error message character ( len =* ), intent ( in ) :: message integer :: iostat if ( message /= '' ) then flush ( unit = stderr , iostat = iostat ) flush ( unit = stdout , iostat = iostat ) if ( value > 0 ) then write ( stderr , '(\" \",a)' ) trim ( message ) else write ( stderr , '(\" \",a)' ) trim ( message ) endif flush ( unit = stderr , iostat = iostat ) endif stop value end subroutine fpm_stop end module fpm_error","tags":"","loc":"sourcefile/error.f90.html"},{"title":"versioning.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of versioning data for comparing packages module fpm_versioning use fpm_error , only : error_t , syntax_error use fpm_strings , only : string_t use regex_module , only : regex implicit none private public :: version_t , new_version public :: regex_version_from_text type :: version_t private !> Version numbers found integer , allocatable :: num (:) contains generic :: operator ( == ) => equals procedure , private :: equals generic :: operator ( /= ) => not_equals procedure , private :: not_equals generic :: operator ( > ) => greater procedure , private :: greater generic :: operator ( < ) => less procedure , private :: less generic :: operator ( >= ) => greater_equals procedure , private :: greater_equals generic :: operator ( <= ) => less_equals procedure , private :: less_equals !> Compare a version against a version constraint (x.x.0 <= v < x.x.HUGE) generic :: operator (. match .) => match procedure , private :: match !> Create a printable string from a version data type procedure :: s end type version_t !> Arbitrary internal limit of the version parser integer , parameter :: max_limit = 3 interface new_version module procedure :: new_version_from_string module procedure :: new_version_from_int end interface new_version contains !> Create a new version from a string subroutine new_version_from_int ( self , num ) !> Instance of the versioning data type ( version_t ), intent ( out ) :: self !> Subversion numbers to define version data integer , intent ( in ) :: num (:) self % num = num end subroutine new_version_from_int !> Create a new version from a string subroutine new_version_from_string ( self , string , error ) !> Instance of the versioning data type ( version_t ), intent ( out ) :: self !> String describing the version information character ( len =* ), intent ( in ) :: string !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: istart , iend , stat , nn integer :: num ( max_limit ) logical :: is_number nn = 0 iend = 0 istart = 0 is_number = . false . do while ( iend < len ( string )) call next ( string , istart , iend , is_number , error ) if ( allocated ( error )) exit if ( is_number ) then if ( nn >= max_limit ) then call token_error ( error , string , istart , iend , & & \"Too many subversions found\" ) exit end if nn = nn + 1 read ( string ( istart : iend ), * , iostat = stat ) num ( nn ) if ( stat /= 0 ) then call token_error ( error , string , istart , iend , & & \"Failed to parse version number\" ) exit end if end if end do if ( allocated ( error )) return if (. not . is_number ) then call token_error ( error , string , istart , iend , & & \"Expected version number, but no characters are left\" ) return end if call new_version ( self , num (: nn )) end subroutine new_version_from_string !> Tokenize a version string subroutine next ( string , istart , iend , is_number , error ) !> String describing the version information character ( len =* ), intent ( in ) :: string !> Start of last token, start of next token on exit integer , intent ( inout ) :: istart !> End of last token on entry, end of next token on exit integer , intent ( inout ) :: iend !> Token produced is a number logical , intent ( inout ) :: is_number !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ii , nn logical :: was_number character :: tok was_number = is_number nn = len ( string ) if ( iend >= nn ) then istart = nn iend = nn return end if ii = min ( iend + 1 , nn ) tok = string ( ii : ii ) is_number = tok /= '.' if ( is_number . eqv . was_number ) then call token_error ( error , string , istart , ii , & & \"Unexpected token found\" ) return end if if (. not . is_number ) then is_number = . false . istart = ii iend = ii return end if istart = ii do ii = min ( iend + 1 , nn ), nn tok = string ( ii : ii ) select case ( tok ) case default call token_error ( error , string , istart , ii , & & \"Invalid character in version number\" ) exit case ( '.' ) exit case ( '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ) iend = ii cycle end select end do end subroutine next !> Create an error on an invalid token, provide some visual context as well subroutine token_error ( error , string , istart , iend , message ) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> String describing the version information character ( len =* ), intent ( in ) :: string !> Start of last token, start of next token on exit integer , intent ( in ) :: istart !> End of last token on entry, end of next token on exit integer , intent ( in ) :: iend !> Error message character ( len =* ), intent ( in ) :: message character ( len =* ), parameter :: nl = new_line ( 'a' ) allocate ( error ) error % message = message // nl // \" | \" // string // nl // & & \" |\" // repeat ( '-' , istart ) // repeat ( '^' , iend - istart + 1 ) end subroutine token_error pure function s ( self ) result ( string ) !> Version number class ( version_t ), intent ( in ) :: self !> Character representation of the version character ( len = :), allocatable :: string integer , parameter :: buffersize = 64 character ( len = buffersize ) :: buffer integer :: ii do ii = 1 , ndigits ( self ) if ( allocated ( string )) then write ( buffer , '(\".\", i0)' ) self % num ( ii ) string = string // trim ( buffer ) else write ( buffer , '(i0)' ) self % num ( ii ) string = trim ( buffer ) end if end do if (. not . allocated ( string )) then string = '0' end if end function s !> Check to version numbers for equality elemental function equals ( lhs , rhs ) result ( is_equal ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> Version match logical :: is_equal is_equal = . not .( lhs > rhs ) if ( is_equal ) then is_equal = . not .( rhs > lhs ) end if end function equals !> Check two versions for inequality elemental function not_equals ( lhs , rhs ) result ( not_equal ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> Version mismatch logical :: not_equal not_equal = lhs > rhs if (. not . not_equal ) then not_equal = rhs > lhs end if end function not_equals !> Relative comparison of two versions elemental function greater ( lhs , rhs ) result ( is_greater ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> First version is greater logical :: is_greater integer :: ii , lhs_size , rhs_size do ii = 1 , min ( ndigits ( lhs ), ndigits ( rhs )) if ( lhs % num ( ii ) /= rhs % num ( ii )) then is_greater = lhs % num ( ii ) > rhs % num ( ii ) return end if end do is_greater = ndigits ( lhs ) > ndigits ( rhs ) if ( is_greater ) then do ii = ndigits ( rhs ) + 1 , ndigits ( lhs ) is_greater = lhs % num ( ii ) > 0 if ( is_greater ) return end do end if end function greater !> Relative comparison of two versions elemental function less ( lhs , rhs ) result ( is_less ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> First version is less logical :: is_less is_less = rhs > lhs end function less !> Relative comparison of two versions elemental function greater_equals ( lhs , rhs ) result ( is_greater_equal ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> First version is greater or equal logical :: is_greater_equal is_greater_equal = . not . ( rhs > lhs ) end function greater_equals !> Relative comparison of two versions elemental function less_equals ( lhs , rhs ) result ( is_less_equal ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> First version is less or equal logical :: is_less_equal is_less_equal = . not . ( lhs > rhs ) end function less_equals !> Try to match first version against second version elemental function match ( lhs , rhs ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> Version match following semantic versioning rules logical :: match type ( version_t ) :: tmp match = . not .( rhs > lhs ) if ( match ) then tmp % num = rhs % num tmp % num ( size ( tmp % num )) = tmp % num ( size ( tmp % num )) + 1 match = tmp > lhs end if end function match !> Number of digits elemental integer function ndigits ( self ) class ( version_t ), intent ( in ) :: self if ( allocated ( self % num )) then ndigits = size ( self % num ) else ndigits = 0 end if end function ndigits ! Extract canonical version flags \"1.0.0\" or \"1.0\" as the first instance inside a text ! (whatever long) using regex type ( string_t ) function regex_version_from_text ( text , what , error ) result ( ver ) character ( * ), intent ( in ) :: text character ( * ), intent ( in ) :: what type ( error_t ), allocatable , intent ( out ) :: error integer :: ire , length if ( len_trim ( text ) <= 0 ) then call syntax_error ( error , 'cannot retrieve ' // what // ' version: empty input string' ) return end if ! Extract 3-sized version \"1.0.4\" ire = regex ( text , '\\d+\\.\\d+\\.\\d+' , length = length ) if ( ire > 0 . and . length > 0 ) then ! Parse version into the object (this should always work) ver = string_t ( text ( ire : ire + length - 1 )) else ! Try 2-sized version \"1.0\" ire = regex ( text , '\\d+\\.\\d+' , length = length ) if ( ire > 0 . and . length > 0 ) then ver = string_t ( text ( ire : ire + length - 1 )) else call syntax_error ( error , 'cannot retrieve ' // what // ' version.' ) end if end if end function regex_version_from_text end module fpm_versioning","tags":"","loc":"sourcefile/versioning.f90.html"},{"title":"executable.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for an executables. !> !> An executable table can currently have the following fields !> !>```toml !>[[ executable ]] !>name = \"string\" !>source-dir = \"path\" !>main = \"file\" !>link = [\"lib\"] !>[executable.dependencies] !>``` module fpm_manifest_executable use fpm_manifest_dependency , only : dependency_config_t , new_dependencies , resize use fpm_error , only : error_t , syntax_error , bad_name_error , fatal_error use fpm_strings , only : string_t , operator ( == ) use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list , serializable_t , add_table , & set_string , set_list implicit none private public :: executable_config_t , new_executable !> Configuation meta data for an executable type , extends ( serializable_t ) :: executable_config_t !> Name of the resulting executable character ( len = :), allocatable :: name !> Source directory for collecting the executable character ( len = :), allocatable :: source_dir !> Name of the source file declaring the main program character ( len = :), allocatable :: main !> Dependency meta data for this executable type ( dependency_config_t ), allocatable :: dependency (:) !> Libraries to link against type ( string_t ), allocatable :: link (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => exe_is_same procedure :: dump_to_toml procedure :: load_from_toml end type executable_config_t character ( * ), parameter , private :: class_name = 'executable_config_t' contains !> Construct a new executable configuration from a TOML data structure subroutine new_executable ( self , table , error ) !> Instance of the executable configuration type ( executable_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve executable name\" ) return end if if ( bad_name_error ( error , 'executable' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"app\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_executable !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) logical :: name_present integer :: ikey name_present = . false . call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Executable section does not provide sufficient entries\" ) return end if do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed as executable entry\" ) exit case ( \"name\" ) name_present = . true . case ( \"source-dir\" , \"main\" , \"dependencies\" , \"link\" ) continue end select end do if ( allocated ( error )) return if (. not . name_present ) then call syntax_error ( error , \"Executable name is not provided, please add a name entry\" ) end if end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the executable configuration class ( executable_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ii character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' , & & fmti = '(\"#\", 1x, a, t30, i0)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Executable target\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % source_dir )) then if ( self % source_dir /= \"app\" . or . pr > 2 ) then write ( unit , fmt ) \"- source directory\" , self % source_dir end if end if if ( allocated ( self % main )) then if ( self % main /= \"main.f90\" . or . pr > 2 ) then write ( unit , fmt ) \"- program source\" , self % main end if end if if ( allocated ( self % dependency )) then if ( size ( self % dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- dependencies\" , size ( self % dependency ) end if do ii = 1 , size ( self % dependency ) call self % dependency ( ii )% info ( unit , pr - 1 ) end do end if end subroutine info logical function exe_is_same ( this , that ) class ( executable_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii exe_is_same = . false . select type ( other => that ) type is ( executable_config_t ) if (. not . this % link == other % link ) return if (. not . allocated ( this % name ). eqv . allocated ( other % name )) return if (. not . this % name == other % name ) return if (. not . allocated ( this % source_dir ). eqv . allocated ( other % source_dir )) return if (. not . this % source_dir == other % source_dir ) return if (. not . allocated ( this % main ). eqv . allocated ( other % main )) return if (. not . this % main == other % main ) return if (. not . allocated ( this % dependency ). eqv . allocated ( other % dependency )) return if ( allocated ( this % dependency )) then if (. not .( size ( this % dependency ) == size ( other % dependency ))) return do ii = 1 , size ( this % dependency ) if (. not .( this % dependency ( ii ) == other % dependency ( ii ))) return end do end if class default ! Not the same type return end select !> All checks passed! exe_is_same = . true . end function exe_is_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( executable_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: ierr , ii type ( toml_table ), pointer :: ptr_deps , ptr character ( 27 ) :: unnamed call set_string ( table , \"name\" , self % name , error ) if ( allocated ( error )) return call set_string ( table , \"source-dir\" , self % source_dir , error ) if ( allocated ( error )) return call set_string ( table , \"main\" , self % main , error ) if ( allocated ( error )) return if ( allocated ( self % dependency )) then ! Create dependency table call add_table ( table , \"dependencies\" , ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , class_name // \" cannot create dependency table \" ) return end if do ii = 1 , size ( self % dependency ) associate ( dep => self % dependency ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( dep % name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_deps , trim ( unnamed ), ptr ) else call add_table ( ptr_deps , dep % name , ptr ) end if if (. not . associated ( ptr )) then call fatal_error ( error , class_name // \" cannot create entry for dependency \" // dep % name ) return end if call dep % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do endif call set_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return 1 format ( 'UNNAMED_DEPENDENCY_' , i0 ) end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( executable_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables type ( toml_key ), allocatable :: keys (:), dep_keys (:) type ( toml_table ), pointer :: ptr_deps , ptr integer :: ii , jj , ierr call table % get_keys ( keys ) call get_value ( table , \"name\" , self % name ) if ( allocated ( error )) return call get_value ( table , \"source-dir\" , self % source_dir ) if ( allocated ( error )) return call get_value ( table , \"main\" , self % main ) if ( allocated ( error )) return call get_list ( table , \"link\" , self % link , error ) find_deps_table : do ii = 1 , size ( keys ) if ( keys ( ii )% key == \"dependencies\" ) then call get_value ( table , keys ( ii ), ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , class_name // ': error retrieving dependency table from TOML table' ) return end if !> Read all dependencies call ptr_deps % get_keys ( dep_keys ) call resize ( self % dependency , size ( dep_keys )) do jj = 1 , size ( dep_keys ) call get_value ( ptr_deps , dep_keys ( jj ), ptr ) call self % dependency ( jj )% load_from_toml ( ptr , error ) if ( allocated ( error )) return end do exit find_deps_table endif end do find_deps_table end subroutine load_from_toml end module fpm_manifest_executable","tags":"","loc":"sourcefile/executable.f90.html"},{"title":"update.f90 – Fortran-lang/fpm","text":"Source Code module fpm_cmd_update use fpm_command_line , only : fpm_update_settings use fpm_dependency , only : dependency_tree_t , new_dependency_tree use fpm_error , only : error_t , fpm_stop use fpm_filesystem , only : exists , mkdir , join_path , delete_file , filewrite use fpm_manifest , only : package_config_t , get_package_data use fpm_toml , only : name_is_json implicit none private public :: cmd_update contains !> Entry point for the update subcommand subroutine cmd_update ( settings ) !> Representation of the command line arguments type ( fpm_update_settings ), intent ( in ) :: settings type ( package_config_t ) :: package type ( dependency_tree_t ) :: deps type ( error_t ), allocatable :: error integer :: ii character ( len = :), allocatable :: cache call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) if (. not . exists ( \"build\" )) then call mkdir ( \"build\" ) call filewrite ( join_path ( \"build\" , \".gitignore\" ),[ \"*\" ]) end if cache = join_path ( \"build\" , \"cache.toml\" ) if ( settings % clean ) call delete_file ( cache ) call new_dependency_tree ( deps , cache = cache , & verbosity = merge ( 2 , 1 , settings % verbose )) call deps % add ( package , error ) call handle_error ( error ) ! Force-update all dependencies if `--clean` if ( settings % clean ) then do ii = 1 , deps % ndep deps % dep ( ii )% update = . true . end do end if if ( settings % fetch_only ) return if ( size ( settings % name ) == 0 ) then call deps % update ( error ) call handle_error ( error ) else do ii = 1 , size ( settings % name ) call deps % update ( trim ( settings % name ( ii )), error ) call handle_error ( error ) end do end if if ( len_trim ( settings % dump ) > 0 ) then call deps % dump ( trim ( settings % dump ), error , json = name_is_json ( trim ( settings % dump ))) call handle_error ( error ) end if end subroutine cmd_update !> Error handling for this command subroutine handle_error ( error ) !> Potential error type ( error_t ), intent ( in ), optional :: error if ( present ( error )) then call fpm_stop ( 1 , '*cmd_update* error: ' // error % message ) end if end subroutine handle_error end module fpm_cmd_update","tags":"","loc":"sourcefile/update.f90.html"},{"title":"example.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for an example. !> !> The example data structure is effectively a decorated version of an executable !> and shares most of its properties, except for the defaults and can be !> handled under most circumstances just like any other executable. !> !> A example table can currently have the following fields !> !>```toml !>[[ example ]] !>name = \"string\" !>source-dir = \"path\" !>main = \"file\" !>link = [\"lib\"] !>[example.dependencies] !>``` module fpm_manifest_example use fpm_manifest_dependency , only : dependency_config_t , new_dependencies use fpm_manifest_executable , only : executable_config_t use fpm_error , only : error_t , syntax_error , bad_name_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list implicit none private public :: example_config_t , new_example !> Configuation meta data for an example type , extends ( executable_config_t ) :: example_config_t contains !> Print information on this instance procedure :: info end type example_config_t contains !> Construct a new example configuration from a TOML data structure subroutine new_example ( self , table , error ) !> Instance of the example configuration type ( example_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve example name\" ) return end if if ( bad_name_error ( error , 'example' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"example\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_example !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) logical :: name_present integer :: ikey name_present = . false . call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Example section does not provide sufficient entries\" ) return end if do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in example entry\" ) exit case ( \"name\" ) name_present = . true . case ( \"source-dir\" , \"main\" , \"dependencies\" , \"link\" ) continue end select end do if ( allocated ( error )) return if (. not . name_present ) then call syntax_error ( error , \"Example name is not provided, please add a name entry\" ) end if end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the example configuration class ( example_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ii character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' , & & fmti = '(\"#\", 1x, a, t30, i0)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Example target\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % source_dir )) then if ( self % source_dir /= \"example\" . or . pr > 2 ) then write ( unit , fmt ) \"- source directory\" , self % source_dir end if end if if ( allocated ( self % main )) then if ( self % main /= \"main.f90\" . or . pr > 2 ) then write ( unit , fmt ) \"- example source\" , self % main end if end if if ( allocated ( self % dependency )) then if ( size ( self % dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- dependencies\" , size ( self % dependency ) end if do ii = 1 , size ( self % dependency ) call self % dependency ( ii )% info ( unit , pr - 1 ) end do end if end subroutine info end module fpm_manifest_example","tags":"","loc":"sourcefile/example.f90.html"},{"title":"fpm_compiler.F90 – Fortran-lang/fpm","text":"Source Code !># Define compiler command options !! !! This module defines compiler options to use for the debug and release builds. ! vendor Fortran C Module output Module include OpenMP Free for OSS ! compiler compiler directory directory ! Gnu gfortran gcc -J -I -fopenmp X ! Intel ifort icc -module -I -qopenmp X ! Intel(Windows) ifort icc /module:path /I /Qopenmp X ! Intel oneAPI ifx icx -module -I -qopenmp X ! PGI pgfortran pgcc -module -I -mp X ! NVIDIA nvfortran nvc -module -I -mp X ! LLVM flang flang clang -module -I -mp X ! LFortran lfortran --- -J -I --openmp X ! Lahey/Futjitsu lfc ? -M -I -openmp ? ! NAG nagfor ? -mdir -I -openmp x ! Cray crayftn craycc -J -I -homp ? ! IBM xlf90 ? -qmoddir -I -qsmp X ! Oracle/Sun ? ? -moddir= -M -xopenmp ? ! Silverfrost FTN95 ftn95 ? ? /MOD_PATH ? ? ! Elbrus ? lcc -J -I -fopenmp ? ! Hewlett Packard ? ? ? ? ? discontinued ! Watcom ? ? ? ? ? discontinued ! PathScale ? ? -module -I -mp discontinued ! G95 ? ? -fmod= -I -fopenmp discontinued ! Open64 ? ? -module -I -mp discontinued ! Unisys ? ? ? ? ? discontinued module fpm_compiler use , intrinsic :: iso_fortran_env , only : stderr => error_unit use fpm_environment , only : & get_os_type , & OS_LINUX , & OS_MACOS , & OS_WINDOWS , & OS_CYGWIN , & OS_SOLARIS , & OS_FREEBSD , & OS_OPENBSD , & OS_UNKNOWN use fpm_filesystem , only : join_path , basename , get_temp_filename , delete_file , unix_path , & & getline , run use fpm_strings , only : split , string_cat , string_t , str_ends_with , str_begins_with_str use fpm_manifest , only : package_config_t use fpm_error , only : error_t , fatal_error use fpm_toml , only : serializable_t , toml_table , set_string , set_value , toml_stat , get_value implicit none public :: compiler_t , new_compiler , archiver_t , new_archiver , get_macros public :: debug enum , bind ( C ) enumerator :: & id_unknown , & id_gcc , & id_f95 , & id_caf , & id_intel_classic_nix , & id_intel_classic_mac , & id_intel_classic_windows , & id_intel_llvm_nix , & id_intel_llvm_windows , & id_intel_llvm_unknown , & id_pgi , & id_nvhpc , & id_nag , & id_flang , & id_flang_new , & id_f18 , & id_ibmxl , & id_cray , & id_lahey , & id_lfortran end enum integer , parameter :: compiler_enum = kind ( id_unknown ) !> Definition of compiler object type , extends ( serializable_t ) :: compiler_t !> Identifier of the compiler integer ( compiler_enum ) :: id = id_unknown !> Path to the Fortran compiler character ( len = :), allocatable :: fc !> Path to the C compiler character ( len = :), allocatable :: cc !> Path to the C++ compiler character ( len = :), allocatable :: cxx !> Print all commands logical :: echo = . true . !> Verbose output of command logical :: verbose = . true . contains !> Get default compiler flags procedure :: get_default_flags !> Get flag for module output directories procedure :: get_module_flag !> Get flag for include directories procedure :: get_include_flag !> Get feature flag procedure :: get_feature_flag !> Get flags for the main linking command procedure :: get_main_flags !> Compile a Fortran object procedure :: compile_fortran !> Compile a C object procedure :: compile_c !> Compile a CPP object procedure :: compile_cpp !> Link executable procedure :: link !> Check whether compiler is recognized procedure :: is_unknown !> Check whether this is an Intel compiler procedure :: is_intel !> Check whether this is a GNU compiler procedure :: is_gnu !> Enumerate libraries, based on compiler and platform procedure :: enumerate_libraries !> Serialization interface procedure :: serializable_is_same => compiler_is_same procedure :: dump_to_toml => compiler_dump procedure :: load_from_toml => compiler_load !> Fortran feature support procedure :: check_fortran_source_runs procedure :: with_xdp procedure :: with_qp !> Return compiler name procedure :: name => compiler_name end type compiler_t !> Definition of archiver object type , extends ( serializable_t ) :: archiver_t !> Path to archiver character ( len = :), allocatable :: ar !> Use response files to pass arguments logical :: use_response_file = . false . !> Print all command logical :: echo = . true . !> Verbose output of command logical :: verbose = . true . contains !> Create static archive procedure :: make_archive !> Serialization interface procedure :: serializable_is_same => ar_is_same procedure :: dump_to_toml procedure :: load_from_toml end type archiver_t !> Create debug printout interface debug module procedure :: debug_compiler module procedure :: debug_archiver end interface debug character ( * ), parameter :: & flag_gnu_coarray = \" -fcoarray=single\" , & flag_gnu_backtrace = \" -fbacktrace\" , & flag_gnu_opt = \" -O3 -funroll-loops\" , & flag_gnu_debug = \" -g\" , & flag_gnu_pic = \" -fPIC\" , & flag_gnu_warn = \" -Wall -Wextra\" , & flag_gnu_check = \" -fcheck=bounds -fcheck=array-temps\" , & flag_gnu_limit = \" -fmax-errors=1\" , & flag_gnu_external = \" -Wimplicit-interface\" , & flag_gnu_openmp = \" -fopenmp\" , & flag_gnu_no_implicit_typing = \" -fimplicit-none\" , & flag_gnu_no_implicit_external = \" -Werror=implicit-interface\" , & flag_gnu_free_form = \" -ffree-form\" , & flag_gnu_fixed_form = \" -ffixed-form\" character ( * ), parameter :: & flag_pgi_backslash = \" -Mbackslash\" , & flag_pgi_traceback = \" -traceback\" , & flag_pgi_debug = \" -g\" , & flag_pgi_check = \" -Mbounds -Mchkptr -Mchkstk\" , & flag_pgi_warn = \" -Minform=inform\" , & flag_pgi_openmp = \" -mp\" , & flag_pgi_free_form = \" -Mfree\" , & flag_pgi_fixed_form = \" -Mfixed\" character ( * ), parameter :: & flag_ibmxl_backslash = \" -qnoescape\" character ( * ), parameter :: & flag_intel_backtrace = \" -traceback\" , & flag_intel_warn = \" -warn all\" , & flag_intel_check = \" -check all\" , & flag_intel_debug = \" -O0 -g\" , & flag_intel_opt = \" -O3\" , & flag_intel_fp = \" -fp-model precise -pc64\" , & flag_intel_align = \" -align all\" , & flag_intel_limit = \" -error-limit 1\" , & flag_intel_pthread = \" -reentrancy threaded\" , & flag_intel_nogen = \" -nogen-interfaces\" , & flag_intel_byterecl = \" -assume byterecl\" , & flag_intel_openmp = \" -qopenmp\" , & flag_intel_free_form = \" -free\" , & flag_intel_fixed_form = \" -fixed\" , & flag_intel_standard_compliance = \" -standard-semantics\" character ( * ), parameter :: & flag_intel_llvm_check = \" -check all,nouninit\" character ( * ), parameter :: & flag_intel_backtrace_win = \" /traceback\" , & flag_intel_warn_win = \" /warn:all\" , & flag_intel_check_win = \" /check:all\" , & flag_intel_debug_win = \" /Od /Z7\" , & flag_intel_opt_win = \" /O3\" , & flag_intel_fp_win = \" /fp:precise\" , & flag_intel_align_win = \" /align:all\" , & flag_intel_limit_win = \" /error-limit:1\" , & flag_intel_pthread_win = \" /reentrancy:threaded\" , & flag_intel_nogen_win = \" /nogen-interfaces\" , & flag_intel_byterecl_win = \" /assume:byterecl\" , & flag_intel_openmp_win = \" /Qopenmp\" , & flag_intel_free_form_win = \" /free\" , & flag_intel_fixed_form_win = \" /fixed\" , & flag_intel_standard_compliance_win = \" /standard-semantics\" character ( * ), parameter :: & flag_nag_coarray = \" -coarray=single\" , & flag_nag_pic = \" -PIC\" , & flag_nag_check = \" -C\" , & flag_nag_debug = \" -g -O0\" , & flag_nag_opt = \" -O4\" , & flag_nag_backtrace = \" -gline\" , & flag_nag_openmp = \" -openmp\" , & flag_nag_free_form = \" -free\" , & flag_nag_fixed_form = \" -fixed\" , & flag_nag_no_implicit_typing = \" -u\" character ( * ), parameter :: & flag_lfortran_opt = \" --fast\" , & flag_lfortran_openmp = \" --openmp\" , & flag_lfortran_implicit_typing = \" --implicit-typing\" , & flag_lfortran_implicit_external = \" --implicit-interface\" , & flag_lfortran_fixed_form = \" --fixed-form\" character ( * ), parameter :: & flag_cray_no_implicit_typing = \" -dl\" , & flag_cray_implicit_typing = \" -el\" , & flag_cray_fixed_form = \" -ffixed\" , & flag_cray_free_form = \" -ffree\" contains function get_default_flags ( self , release ) result ( flags ) class ( compiler_t ), intent ( in ) :: self logical , intent ( in ) :: release character ( len = :), allocatable :: flags if ( release ) then call get_release_compile_flags ( self % id , flags ) else call get_debug_compile_flags ( self % id , flags ) end if end function get_default_flags subroutine get_release_compile_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( out ) :: flags select case ( id ) case default flags = \"\" case ( id_caf ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit case ( id_gcc ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_coarray case ( id_f95 ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit case ( id_nvhpc ) flags = & flag_pgi_backslash case ( id_ibmxl ) flags = & flag_ibmxl_backslash case ( id_intel_classic_nix ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_classic_mac ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_classic_windows ) flags = & flag_intel_opt_win // & flag_intel_fp_win // & flag_intel_align_win // & flag_intel_limit_win // & flag_intel_pthread_win // & flag_intel_nogen_win // & flag_intel_byterecl_win case ( id_intel_llvm_nix ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_llvm_windows ) flags = & flag_intel_opt_win // & flag_intel_fp_win // & flag_intel_align_win // & flag_intel_limit_win // & flag_intel_pthread_win // & flag_intel_nogen_win // & flag_intel_byterecl_win case ( id_nag ) flags = & flag_nag_opt // & flag_nag_coarray // & flag_nag_pic case ( id_lfortran ) flags = & flag_lfortran_opt end select end subroutine get_release_compile_flags subroutine get_debug_compile_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( out ) :: flags select case ( id ) case default flags = \"\" case ( id_caf ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & flag_gnu_backtrace case ( id_gcc ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & flag_gnu_backtrace // & flag_gnu_coarray case ( id_f95 ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & ' -Wno-maybe-uninitialized -Wno-uninitialized' // & flag_gnu_backtrace case ( id_nvhpc ) flags = & flag_pgi_warn // & flag_pgi_backslash // & flag_pgi_check // & flag_pgi_traceback case ( id_ibmxl ) flags = & flag_ibmxl_backslash case ( id_intel_classic_nix ) flags = & flag_intel_warn // & flag_intel_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_classic_mac ) flags = & flag_intel_warn // & flag_intel_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_classic_windows ) flags = & flag_intel_warn_win // & flag_intel_check_win // & flag_intel_limit_win // & flag_intel_debug_win // & flag_intel_byterecl_win // & flag_intel_backtrace_win case ( id_intel_llvm_nix ) flags = & flag_intel_warn // & flag_intel_llvm_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_llvm_windows ) flags = & flag_intel_warn_win // & flag_intel_check_win // & flag_intel_limit_win // & flag_intel_debug_win // & flag_intel_byterecl_win case ( id_nag ) flags = & flag_nag_debug // & flag_nag_check // & flag_nag_backtrace // & flag_nag_coarray // & flag_nag_pic case ( id_lfortran ) flags = \"\" end select end subroutine get_debug_compile_flags pure subroutine set_cpp_preprocessor_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( inout ) :: flags character ( len = :), allocatable :: flag_cpp_preprocessor !> Modify the flag_cpp_preprocessor on the basis of the compiler. select case ( id ) case default flag_cpp_preprocessor = \"\" case ( id_caf , id_gcc , id_f95 , id_nvhpc ) flag_cpp_preprocessor = \"-cpp\" case ( id_intel_classic_windows , id_intel_llvm_windows ) flag_cpp_preprocessor = \"/fpp\" case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , id_nag ) flag_cpp_preprocessor = \"-fpp\" case ( id_lfortran ) flag_cpp_preprocessor = \"--cpp\" end select flags = flag_cpp_preprocessor // flags end subroutine set_cpp_preprocessor_flags !> This function will parse and read the macros list and !> return them as defined flags. function get_macros ( id , macros_list , version ) result ( macros ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( in ) :: version type ( string_t ), allocatable , intent ( in ) :: macros_list (:) character ( len = :), allocatable :: macros character ( len = :), allocatable :: macro_definition_symbol character (:), allocatable :: valued_macros (:) integer :: i if (. not . allocated ( macros_list )) then macros = \"\" return end if !> Set macro defintion symbol on the basis of compiler used select case ( id ) case default macro_definition_symbol = \" -D\" case ( id_intel_classic_windows , id_intel_llvm_windows ) macro_definition_symbol = \" /D\" end select !> Check if macros are not allocated. if (. not . allocated ( macros )) then macros = \"\" end if do i = 1 , size ( macros_list ) !> Split the macro name and value. call split ( macros_list ( i )% s , valued_macros , delimiters = \"=\" ) if ( size ( valued_macros ) > 1 ) then !> Check if the value of macro starts with '{' character. if ( str_begins_with_str ( trim ( valued_macros ( size ( valued_macros ))), \"{\" )) then !> Check if the value of macro ends with '}' character. if ( str_ends_with ( trim ( valued_macros ( size ( valued_macros ))), \"}\" )) then !> Check if the string contains \"version\" as substring. if ( index ( valued_macros ( size ( valued_macros )), \"version\" ) /= 0 ) then !> These conditions are placed in order to ensure proper spacing between the macros. macros = macros // macro_definition_symbol // trim ( valued_macros ( 1 )) // '=' // version cycle end if end if end if end if macros = macros // macro_definition_symbol // macros_list ( i )% s end do end function get_macros function get_include_flag ( self , path ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: flags select case ( self % id ) case default flags = \"-I \" // path case ( id_caf , id_gcc , id_f95 , id_cray , id_nvhpc , id_pgi , & & id_flang , id_flang_new , id_f18 , & & id_intel_classic_nix , id_intel_classic_mac , & & id_intel_llvm_nix , id_lahey , id_nag , id_ibmxl , & & id_lfortran ) flags = \"-I \" // path case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = \"/I\" // path end select end function get_include_flag function get_module_flag ( self , path ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: flags select case ( self % id ) case default flags = \"-module \" // path case ( id_caf , id_gcc , id_f95 , id_cray , id_lfortran ) flags = \"-J \" // path case ( id_nvhpc , id_pgi , id_flang ) flags = \"-module \" // path case ( id_flang_new , id_f18 ) flags = \"-module-dir \" // path case ( id_intel_classic_nix , id_intel_classic_mac , & & id_intel_llvm_nix ) flags = \"-module \" // path case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = \"/module:\" // path case ( id_lahey ) flags = \"-M \" // path case ( id_nag ) flags = \"-mdir \" // path case ( id_ibmxl ) flags = \"-qmoddir \" // path end select end function get_module_flag function get_feature_flag ( self , feature ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: feature character ( len = :), allocatable :: flags flags = \"\" select case ( feature ) case ( \"no-implicit-typing\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_no_implicit_typing case ( id_nag ) flags = flag_nag_no_implicit_typing case ( id_cray ) flags = flag_cray_no_implicit_typing end select case ( \"implicit-typing\" ) select case ( self % id ) case ( id_cray ) flags = flag_cray_implicit_typing case ( id_lfortran ) flags = flag_lfortran_implicit_typing end select case ( \"no-implicit-external\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_no_implicit_external end select case ( \"implicit-external\" ) select case ( self % id ) case ( id_lfortran ) flags = flag_lfortran_implicit_external end select case ( \"free-form\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_free_form case ( id_pgi , id_nvhpc , id_flang ) flags = flag_pgi_free_form case ( id_nag ) flags = flag_nag_free_form case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , & & id_intel_llvm_unknown ) flags = flag_intel_free_form case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = flag_intel_free_form_win case ( id_cray ) flags = flag_cray_free_form end select case ( \"fixed-form\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_fixed_form case ( id_pgi , id_nvhpc , id_flang ) flags = flag_pgi_fixed_form case ( id_nag ) flags = flag_nag_fixed_form case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , & & id_intel_llvm_unknown ) flags = flag_intel_fixed_form case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = flag_intel_fixed_form_win case ( id_cray ) flags = flag_cray_fixed_form case ( id_lfortran ) flags = flag_lfortran_fixed_form end select case ( \"default-form\" ) continue case default error stop \"Unknown feature '\" // feature // \"'\" end select end function get_feature_flag !> Get special flags for the main linker subroutine get_main_flags ( self , language , flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: language character ( len = :), allocatable , intent ( out ) :: flags flags = \"\" select case ( language ) case ( \"fortran\" ) flags = \"\" case ( \"c\" ) ! If the main program is on a C/C++ source, the Intel Fortran compiler requires option ! -nofor-main to avoid \"duplicate main\" errors. ! https://stackoverflow.com/questions/36221612/p3dfft-compilation-ifort-compiler-error-multiple-definiton-of-main select case ( self % id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix ) flags = '-nofor-main' case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = '/nofor-main' case ( id_pgi , id_nvhpc ) flags = '-Mnomain' end select case ( \"c++\" , \"cpp\" , \"cxx\" ) select case ( self % id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix ) flags = '-nofor-main' case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = '/nofor-main' case ( id_pgi , id_nvhpc ) flags = '-Mnomain' end select case default error stop \"Unknown language '\" // language // '\", try \"fortran\", \"c\", \"c++\"' end select end subroutine get_main_flags subroutine get_default_c_compiler ( f_compiler , c_compiler ) character ( len =* ), intent ( in ) :: f_compiler character ( len = :), allocatable , intent ( out ) :: c_compiler integer ( compiler_enum ) :: id id = get_compiler_id ( f_compiler ) select case ( id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows ) c_compiler = 'icc' case ( id_intel_llvm_nix , id_intel_llvm_windows ) c_compiler = 'icx' case ( id_flang , id_flang_new , id_f18 ) c_compiler = 'clang' case ( id_ibmxl ) c_compiler = 'xlc' case ( id_lfortran ) c_compiler = 'cc' case ( id_gcc ) c_compiler = 'gcc' case default ! Fall-back to using Fortran compiler c_compiler = f_compiler end select end subroutine get_default_c_compiler !> Get C++ Compiler. subroutine get_default_cxx_compiler ( f_compiler , cxx_compiler ) character ( len =* ), intent ( in ) :: f_compiler character ( len = :), allocatable , intent ( out ) :: cxx_compiler integer ( compiler_enum ) :: id id = get_compiler_id ( f_compiler ) select case ( id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows ) cxx_compiler = 'icpc' case ( id_intel_llvm_nix , id_intel_llvm_windows ) cxx_compiler = 'icpx' case ( id_flang , id_flang_new , id_f18 ) cxx_compiler = 'clang++' case ( id_ibmxl ) cxx_compiler = 'xlc++' case ( id_lfortran ) cxx_compiler = 'cc' case ( id_gcc ) cxx_compiler = 'g++' case default ! Fall-back to using Fortran compiler cxx_compiler = f_compiler end select end subroutine get_default_cxx_compiler function get_compiler_id ( compiler ) result ( id ) character ( len =* ), intent ( in ) :: compiler integer ( kind = compiler_enum ) :: id character ( len = :), allocatable :: full_command , full_command_parts (:), command , output integer :: stat , io ! Check whether we are dealing with an MPI compiler wrapper first if ( check_compiler ( compiler , \"mpifort\" ) & & . or . check_compiler ( compiler , \"mpif90\" ) & & . or . check_compiler ( compiler , \"mpif77\" )) then output = get_temp_filename () call run ( compiler // \" -show > \" // output // \" 2>&1\" , & & echo = . false ., exitstat = stat ) if ( stat == 0 ) then open ( file = output , newunit = io , iostat = stat ) if ( stat == 0 ) call getline ( io , full_command , stat ) close ( io , iostat = stat ) ! If we get a command from the wrapper, we will try to identify it call split ( full_command , full_command_parts , delimiters = ' ' ) if ( size ( full_command_parts ) > 0 ) then command = trim ( full_command_parts ( 1 )) endif if ( allocated ( command )) then id = get_id ( command ) if ( id /= id_unknown ) return end if end if end if id = get_id ( compiler ) end function get_compiler_id function get_id ( compiler ) result ( id ) character ( len =* ), intent ( in ) :: compiler integer ( kind = compiler_enum ) :: id if ( check_compiler ( compiler , \"gfortran\" )) then id = id_gcc return end if if ( check_compiler ( compiler , \"f95\" )) then id = id_f95 return end if if ( check_compiler ( compiler , \"caf\" )) then id = id_caf return end if if ( check_compiler ( compiler , \"ifort\" )) then select case ( get_os_type ()) case default id = id_intel_classic_nix case ( OS_MACOS ) id = id_intel_classic_mac case ( OS_WINDOWS , OS_CYGWIN ) id = id_intel_classic_windows end select return end if if ( check_compiler ( compiler , \"ifx\" )) then select case ( get_os_type ()) case default id = id_intel_llvm_nix case ( OS_WINDOWS , OS_CYGWIN ) id = id_intel_llvm_windows end select return end if if ( check_compiler ( compiler , \"nvfortran\" )) then id = id_nvhpc return end if if ( check_compiler ( compiler , \"pgfortran\" ) & & . or . check_compiler ( compiler , \"pgf90\" ) & & . or . check_compiler ( compiler , \"pgf95\" )) then id = id_pgi return end if if ( check_compiler ( compiler , \"nagfor\" )) then id = id_nag return end if if ( check_compiler ( compiler , \"flang-new\" )) then id = id_flang_new return end if if ( check_compiler ( compiler , \"f18\" )) then id = id_f18 return end if if ( check_compiler ( compiler , \"flang\" )) then id = id_flang return end if if ( check_compiler ( compiler , \"xlf90\" )) then id = id_ibmxl return end if if ( check_compiler ( compiler , \"crayftn\" )) then id = id_cray return end if if ( check_compiler ( compiler , \"lfc\" )) then id = id_lahey return end if if ( check_compiler ( compiler , \"lfortran\" )) then id = id_lfortran return end if id = id_unknown end function get_id function check_compiler ( compiler , expected ) result ( match ) character ( len =* ), intent ( in ) :: compiler character ( len =* ), intent ( in ) :: expected logical :: match match = compiler == expected if (. not . match ) then match = index ( basename ( compiler ), expected ) > 0 end if end function check_compiler pure function is_unknown ( self ) class ( compiler_t ), intent ( in ) :: self logical :: is_unknown is_unknown = self % id == id_unknown end function is_unknown pure logical function is_intel ( self ) class ( compiler_t ), intent ( in ) :: self is_intel = any ( self % id == [ id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows , & id_intel_llvm_nix , id_intel_llvm_windows , id_intel_llvm_unknown ]) end function is_intel pure logical function is_gnu ( self ) class ( compiler_t ), intent ( in ) :: self is_gnu = any ( self % id == [ id_f95 , id_gcc , id_caf ]) end function is_gnu !> !> Enumerate libraries, based on compiler and platform !> function enumerate_libraries ( self , prefix , libs ) result ( r ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: prefix type ( string_t ), intent ( in ) :: libs (:) character ( len = :), allocatable :: r if ( self % id == id_intel_classic_windows . or . & self % id == id_intel_llvm_windows ) then r = prefix // \" \" // string_cat ( libs , \".lib \" ) // \".lib\" else r = prefix // \" -l\" // string_cat ( libs , \" -l\" ) end if end function enumerate_libraries !> Create new compiler instance subroutine new_compiler ( self , fc , cc , cxx , echo , verbose ) !> New instance of the compiler type ( compiler_t ), intent ( out ) :: self !> Fortran compiler name or path character ( len =* ), intent ( in ) :: fc !> C compiler name or path character ( len =* ), intent ( in ) :: cc !> C++ Compiler name or path character ( len =* ), intent ( in ) :: cxx !> Echo compiler command logical , intent ( in ) :: echo !> Verbose mode: dump compiler output logical , intent ( in ) :: verbose self % id = get_compiler_id ( fc ) self % echo = echo self % verbose = verbose self % fc = fc if ( len_trim ( cc ) > 0 ) then self % cc = cc else call get_default_c_compiler ( self % fc , self % cc ) end if if ( len_trim ( cxx ) > 0 ) then self % cxx = cxx else call get_default_cxx_compiler ( self % fc , self % cxx ) end if end subroutine new_compiler !> Create new archiver instance subroutine new_archiver ( self , ar , echo , verbose ) !> New instance of the archiver type ( archiver_t ), intent ( out ) :: self !> User provided archiver command character ( len =* ), intent ( in ) :: ar !> Echo compiler command logical , intent ( in ) :: echo !> Verbose mode: dump compiler output logical , intent ( in ) :: verbose integer :: estat , os_type character ( len =* ), parameter :: arflags = \" -rs \" , libflags = \" /OUT:\" if ( len_trim ( ar ) > 0 ) then ! Check first for ar-like commands if ( check_compiler ( ar , \"ar\" )) then self % ar = ar // arflags end if ! Check for lib-like commands if ( check_compiler ( ar , \"lib\" )) then self % ar = ar // libflags end if ! Fallback and assume ar-like behaviour self % ar = ar // arflags else os_type = get_os_type () if ( os_type /= OS_WINDOWS . and . os_type /= OS_UNKNOWN ) then self % ar = \"ar\" // arflags else ! Attempt \"ar\" call execute_command_line ( \"ar --version > \" // get_temp_filename () // \" 2>&1\" , & & exitstat = estat ) if ( estat == 0 ) then self % ar = \"ar\" // arflags else ! Then \"gcc-ar\" call execute_command_line ( \"gcc-ar --version > \" // get_temp_filename () // \" 2>&1\" , & & exitstat = estat ) if ( estat /= 0 ) then self % ar = \"lib\" // libflags else self % ar = \"gcc-ar\" // arflags end if endif end if end if self % use_response_file = os_type == OS_WINDOWS self % echo = echo self % verbose = verbose end subroutine new_archiver !> Compile a Fortran object subroutine compile_fortran ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % fc // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_fortran !> Compile a C object subroutine compile_c ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % cc // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_c !> Compile a CPP object subroutine compile_cpp ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % cxx // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_cpp !> Link an executable subroutine link ( self , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % fc // \" \" // args // \" -o \" // output , echo = self % echo , & & verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine link !> Create an archive !> @todo For Windows OS, use the local `delete_file_win32` in stead of `delete_file`. !> This may be related to a bug in Mingw64-openmp and is expected to be resolved in the future, !> see issue #707, #708 and #808. subroutine make_archive ( self , output , args , log_file , stat ) !> Instance of the archiver object class ( archiver_t ), intent ( in ) :: self !> Name of the archive to generate character ( len =* ), intent ( in ) :: output !> Object files to include into the archive type ( string_t ), intent ( in ) :: args (:) !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat if ( self % use_response_file ) then call write_response_file ( output // \".resp\" , args ) call run ( self % ar // output // \" @\" // output // \".resp\" , echo = self % echo , & & verbose = self % verbose , redirect = log_file , exitstat = stat ) call delete_file_win32 ( output // \".resp\" ) else call run ( self % ar // output // \" \" // string_cat ( args , \" \" ), & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end if contains subroutine delete_file_win32 ( file ) character ( len =* ), intent ( in ) :: file logical :: exist integer :: unit , iostat inquire ( file = file , exist = exist ) if ( exist ) then open ( file = file , newunit = unit ) close ( unit , status = 'delete' , iostat = iostat ) end if end subroutine delete_file_win32 end subroutine make_archive !> Response files allow to read command line options from files. !> Whitespace is used to separate the arguments, we will use newlines !> as separator to create readable response files which can be inspected !> in case of errors. subroutine write_response_file ( name , argv ) character ( len =* ), intent ( in ) :: name type ( string_t ), intent ( in ) :: argv (:) integer :: iarg , io open ( file = name , newunit = io , status = 'replace' ) do iarg = 1 , size ( argv ) write ( io , '(a)' ) unix_path ( argv ( iarg )% s ) end do close ( io ) end subroutine write_response_file !> String representation of a compiler object pure function debug_compiler ( self ) result ( repr ) !> Instance of the compiler object type ( compiler_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: repr repr = 'fc=\"' // self % fc // '\", cc=\"' // self % cc // '\"' end function debug_compiler !> String representation of an archiver object pure function debug_archiver ( self ) result ( repr ) !> Instance of the archiver object type ( archiver_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: repr repr = 'ar=\"' // self % ar // '\"' end function debug_archiver !> Check that two archiver_t objects are equal logical function ar_is_same ( this , that ) class ( archiver_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that ar_is_same = . false . select type ( other => that ) type is ( archiver_t ) if (. not .( this % ar == other % ar )) return if (. not .( this % use_response_file . eqv . other % use_response_file )) return if (. not .( this % echo . eqv . other % echo )) return if (. not .( this % verbose . eqv . other % verbose )) return class default ! Not the same type return end select !> All checks passed! ar_is_same = . true . end function ar_is_same !> Dump dependency to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( archiver_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Path to archiver call set_string ( table , \"ar\" , self % ar , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"use-response-file\" , self % use_response_file , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"echo\" , self % echo , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"verbose\" , self % verbose , error , 'archiver_t' ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( archiver_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"ar\" , self % ar ) call get_value ( table , \"use-response-file\" , self % use_response_file , error , 'archiver_t' ) if ( allocated ( error )) return call get_value ( table , \"echo\" , self % echo , error , 'archiver_t' ) if ( allocated ( error )) return call get_value ( table , \"verbose\" , self % verbose , error , 'archiver_t' ) if ( allocated ( error )) return end subroutine load_from_toml !> Check that two compiler_t objects are equal logical function compiler_is_same ( this , that ) class ( compiler_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that compiler_is_same = . false . select type ( other => that ) type is ( compiler_t ) if (. not .( this % id == other % id )) return if (. not .( this % fc == other % fc )) return if (. not .( this % cc == other % cc )) return if (. not .( this % cxx == other % cxx )) return if (. not .( this % echo . eqv . other % echo )) return if (. not .( this % verbose . eqv . other % verbose )) return class default ! Not the same type return end select !> All checks passed! compiler_is_same = . true . end function compiler_is_same !> Dump dependency to toml table subroutine compiler_dump ( self , table , error ) !> Instance of the serializable object class ( compiler_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_value ( table , \"id\" , self % id , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"fc\" , self % fc , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"cc\" , self % cc , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"cxx\" , self % cxx , error , 'compiler_t' ) if ( allocated ( error )) return call set_value ( table , \"echo\" , self % echo , error , 'compiler_t' ) if ( allocated ( error )) return call set_value ( table , \"verbose\" , self % verbose , error , 'compiler_t' ) if ( allocated ( error )) return end subroutine compiler_dump !> Read dependency from toml table (no checks made at this stage) subroutine compiler_load ( self , table , error ) !> Instance of the serializable object class ( compiler_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"id\" , self % id , error , 'compiler_t' ) if ( allocated ( error )) return call get_value ( table , \"fc\" , self % fc ) call get_value ( table , \"cc\" , self % cc ) call get_value ( table , \"cxx\" , self % cxx ) call get_value ( table , \"echo\" , self % echo , error , 'compiler_t' ) if ( allocated ( error )) return call get_value ( table , \"verbose\" , self % verbose , error , 'compiler_t' ) if ( allocated ( error )) return end subroutine compiler_load !> Return a compiler name string pure function compiler_name ( self ) result ( name ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: name select case ( self % id ) case ( id_gcc ); name = \"gfortran\" case ( id_f95 ); name = \"f95\" case ( id_caf ); name = \"caf\" case ( id_intel_classic_nix ); name = \"ifort\" case ( id_intel_classic_mac ); name = \"ifort\" case ( id_intel_classic_windows ); name = \"ifort\" case ( id_intel_llvm_nix ); name = \"ifx\" case ( id_intel_llvm_windows ); name = \"ifx\" case ( id_intel_llvm_unknown ); name = \"ifx\" case ( id_pgi ); name = \"pgfortran\" case ( id_nvhpc ); name = \"nvfortran\" case ( id_nag ); name = \"nagfor\" case ( id_flang ); name = \"flang\" case ( id_flang_new ); name = \"flang-new\" case ( id_f18 ); name = \"f18\" case ( id_ibmxl ); name = \"xlf90\" case ( id_cray ); name = \"crayftn\" case ( id_lahey ); name = \"lfc\" case ( id_lfortran ); name = \"lFortran\" case default ; name = \"invalid/unknown\" end select end function compiler_name !> Run a single-source Fortran program using the current compiler !> Compile a Fortran object logical function check_fortran_source_runs ( self , input ) result ( success ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Program Source character ( len =* ), intent ( in ) :: input integer :: stat , unit character (:), allocatable :: source , object , logf , exe success = . false . !> Create temporary source file exe = get_temp_filename () source = exe // '.f90' object = exe // '.o' logf = exe // '.log' open ( newunit = unit , file = source , action = 'readwrite' , iostat = stat ) if ( stat /= 0 ) return !> Write contents write ( unit , * ) input close ( unit ) !> Compile and link program call self % compile_fortran ( source , object , self % get_default_flags ( release = . false .), logf , stat ) if ( stat == 0 ) & call self % link ( exe , self % get_default_flags ( release = . false .) // \" \" // object , logf , stat ) !> Run and retrieve exit code if ( stat == 0 ) & call run ( exe , echo = . false ., exitstat = stat , verbose = . false ., redirect = logf ) !> Successful exit on 0 exit code success = stat == 0 !> Delete files open ( newunit = unit , file = source , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = object , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = logf , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = exe , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) end function check_fortran_source_runs !> Check if the current compiler supports 128-bit real precision logical function with_qp ( self ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self with_qp = self % check_fortran_source_runs & ( 'if (selected_real_kind(33) == -1) stop 1; end' ) end function with_qp !> Check if the current compiler supports 80-bit \"extended\" real precision logical function with_xdp ( self ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self with_xdp = self % check_fortran_source_runs & ( 'if (any(selected_real_kind(18) == [-1, selected_real_kind(33)])) stop 1; end' ) end function with_xdp end module fpm_compiler","tags":"","loc":"sourcefile/fpm_compiler.f90.html"},{"title":"fpm_command_line.f90 – Fortran-lang/fpm","text":"Source Code !># Definition of the command line interface !> !> This module uses [M_CLI2](https://github.com/urbanjost/M_CLI2) to define !> the command line interface. !> To define a command line interface create a new command settings type !> from the [[fpm_cmd_settings]] base class or the respective parent command !> settings. !> !> The subcommand is selected by the first non-option argument in the command !> line. In the subcase block the actual command line is defined and transferred !> to an instance of the [[fpm_cmd_settings]], the actual type is used by the !> *fpm* main program to determine which command entry point is chosen. !> !> To add a new subcommand add a new case to select construct and specify the !> wanted command line and the expected default values. !> Some of the following points also apply if you add a new option or argument !> to an existing *fpm* subcommand. !> At this point you should create a help page for the new command in a simple !> catman-like format as well in the ``set_help`` procedure. !> Make sure to register new subcommands in the ``fpm-manual`` command by adding !> them to the manual character array and in the help/manual case as well. !> You should add the new command to the synopsis section of the ``fpm-list``, !> ``fpm-help`` and ``fpm --list`` help pages below to make sure the help output !> is complete and consistent as well. module fpm_command_line use fpm_environment , only : get_os_type , get_env , & OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_WINDOWS , & OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD , OS_NAME use M_CLI2 , only : set_args , lget , sget , unnamed , remaining , specified use M_CLI2 , only : get_subcommand , CLI_RESPONSE_FILE use fpm_strings , only : lower , split , to_fortran_name , is_fortran_name , remove_characters_in_set , & string_t , glob use fpm_filesystem , only : basename , canon_path , which , run use fpm_environment , only : get_command_arguments_quoted use fpm_error , only : fpm_stop , error_t use fpm_os , only : get_current_directory use fpm_release , only : fpm_version , version_t use , intrinsic :: iso_fortran_env , only : stdin => input_unit , & & stdout => output_unit , & & stderr => error_unit implicit none private public :: fpm_cmd_settings , & fpm_build_settings , & fpm_install_settings , & fpm_export_settings , & fpm_new_settings , & fpm_run_settings , & fpm_test_settings , & fpm_update_settings , & fpm_clean_settings , & fpm_publish_settings , & get_command_line_settings , & get_fpm_env type , abstract :: fpm_cmd_settings character ( len = :), allocatable :: working_dir logical :: verbose = . true . end type integer , parameter :: ibug = 4096 type , extends ( fpm_cmd_settings ) :: fpm_new_settings character ( len = :), allocatable :: name logical :: with_executable = . false . logical :: with_test = . false . logical :: with_lib = . true . logical :: with_example = . false . logical :: with_full = . false . logical :: with_bare = . false . logical :: backfill = . true . end type type , extends ( fpm_cmd_settings ) :: fpm_build_settings logical :: list = . false . logical :: show_model = . false . logical :: build_tests = . false . logical :: prune = . true . character ( len = :), allocatable :: dump character ( len = :), allocatable :: compiler character ( len = :), allocatable :: c_compiler character ( len = :), allocatable :: cxx_compiler character ( len = :), allocatable :: archiver character ( len = :), allocatable :: profile character ( len = :), allocatable :: flag character ( len = :), allocatable :: cflag character ( len = :), allocatable :: cxxflag character ( len = :), allocatable :: ldflag end type type , extends ( fpm_build_settings ) :: fpm_run_settings character ( len = ibug ), allocatable :: name (:) character ( len = :), allocatable :: args ! passed to the app character ( len = :), allocatable :: runner character ( len = :), allocatable :: runner_args ! passed to the runner logical :: example contains procedure :: runner_command procedure :: name_ID end type type , extends ( fpm_run_settings ) :: fpm_test_settings end type type , extends ( fpm_build_settings ) :: fpm_install_settings character ( len = :), allocatable :: prefix character ( len = :), allocatable :: bindir character ( len = :), allocatable :: libdir character ( len = :), allocatable :: includedir logical :: no_rebuild end type !> Settings for interacting and updating with project dependencies type , extends ( fpm_cmd_settings ) :: fpm_update_settings character ( len = ibug ), allocatable :: name (:) character ( len = :), allocatable :: dump logical :: fetch_only logical :: clean end type !> Settings for exporting model data type , extends ( fpm_build_settings ) :: fpm_export_settings character ( len = :), allocatable :: dump_manifest character ( len = :), allocatable :: dump_dependencies character ( len = :), allocatable :: dump_model end type type , extends ( fpm_cmd_settings ) :: fpm_clean_settings logical :: clean_skip = . false . logical :: clean_all = . false . logical :: registry_cache = . false . end type type , extends ( fpm_build_settings ) :: fpm_publish_settings logical :: show_package_version = . false . logical :: show_upload_data = . false . logical :: is_dry_run = . false . character ( len = :), allocatable :: token end type character ( len = :), allocatable :: name character ( len = :), allocatable :: os_type character ( len = ibug ), allocatable :: names (:) character ( len = :), allocatable :: tnames (:) character ( len = :), allocatable :: version_text (:) character ( len = :), allocatable :: help_new (:), help_fpm (:), help_run (:), & & help_test (:), help_build (:), help_usage (:), help_runner (:), & & help_text (:), help_install (:), help_help (:), help_update (:), & & help_list (:), help_list_dash (:), help_list_nodash (:), & & help_clean (:), help_publish (:) character ( len = 20 ), parameter :: manual ( * ) = [ character ( len = 20 ) :: & & ' ' , 'fpm' , 'new' , 'build' , 'run' , 'clean' , & & 'test' , 'runner' , 'install' , 'update' , 'list' , 'help' , 'version' , 'publish' ] character ( len = :), allocatable :: val_runner , val_compiler , val_flag , val_cflag , val_cxxflag , val_ldflag , & val_profile , val_runner_args , val_dump ! '12345678901234567890123456789012345678901234567890123456789012345678901234567890',& character ( len = 80 ), parameter :: help_text_build_common ( * ) = [ character ( len = 80 ) :: & ' --profile PROF Selects the compilation profile for the build. ' ,& ' Currently available profiles are \"release\" for ' ,& ' high optimization and \"debug\" for full debug options. ' ,& ' If --flag is not specified the \"debug\" flags are the ' ,& ' default. ' ,& ' --no-prune Disable tree-shaking/pruning of unused module dependencies ' & ] ! '12345678901234567890123456789012345678901234567890123456789012345678901234567890',& character ( len = 80 ), parameter :: help_text_compiler ( * ) = [ character ( len = 80 ) :: & ' --compiler NAME Specify a compiler name. The default is \"gfortran\" ' ,& ' unless set by the environment variable FPM_FC. ' ,& ' --c-compiler NAME Specify the C compiler name. Automatically determined by ' ,& ' default unless set by the environment variable FPM_CC. ' ,& ' --cxx-compiler NAME Specify the C++ compiler name. Automatically determined by' ,& ' default unless set by the environment variable FPM_CXX. ' ,& ' --archiver NAME Specify the archiver name. Automatically determined by ' ,& ' default unless set by the environment variable FPM_AR. ' & ] ! '12345678901234567890123456789012345678901234567890123456789012345678901234567890',& character ( len = 80 ), parameter :: help_text_flag ( * ) = [ character ( len = 80 ) :: & ' --flag FFLAGS selects compile arguments for the build, the default value is' ,& ' set by the FPM_FFLAGS environment variable. These are added ' ,& ' to the profile options if --profile is specified, else these ' ,& ' are added to the defaults. To override the defaults, use the ' ,& ' keyword [fortran] in the manifest. Note object and .mod ' ,& ' directory locations are always built in. ' ,& ' --c-flag CFLAGS selects compile arguments specific for C source in the build.' ,& ' The default value is set by the FPM_CFLAGS environment ' ,& ' variable. ' ,& ' --cxx-flag CFLAGS selects compile arguments specific for C++ source in the ' ,& ' build. The default value is set by the FPM_CXXFLAGS ' ,& ' environment variable. ' ,& ' --link-flag LDFLAGS select arguments passed to the linker for the build. The ' ,& ' default value is set by the FPM_LDFLAGS environment variable.' & ] character ( len = 80 ), parameter :: help_text_environment ( * ) = [ character ( len = 80 ) :: & 'ENVIRONMENT VARIABLES' ,& ' FPM_FC sets the path to the Fortran compiler used for the build,' , & ' will be overwritten by --compiler command line option' , & '' , & ' FPM_FFLAGS sets the arguments for the Fortran compiler' , & ' will be overwritten by --flag command line option' , & '' , & ' FPM_CC sets the path to the C compiler used for the build,' , & ' will be overwritten by --c-compiler command line option' , & '' , & ' FPM_CFLAGS sets the arguments for the C compiler' , & ' will be overwritten by --c-flag command line option' , & '' , & ' FPM_CXX sets the path to the C++ compiler used for the build,' , & ' will be overwritten by --cxx-compiler command line option' , & '' , & ' FPM_CXXFLAGS sets the arguments for the C++ compiler' , & ' will be overwritten by --cxx-flag command line option' , & '' , & ' FPM_AR sets the path to the archiver used for the build,' , & ' will be overwritten by --archiver command line option' , & '' , & ' FPM_LDFLAGS sets additional link arguments for creating executables' , & ' will be overwritten by --link-flag command line option' & ] contains subroutine get_command_line_settings ( cmd_settings ) class ( fpm_cmd_settings ), allocatable , intent ( out ) :: cmd_settings integer , parameter :: widest = 256 character ( len = 4096 ) :: cmdarg integer :: i integer :: os type ( fpm_install_settings ), allocatable :: install_settings type ( fpm_publish_settings ), allocatable :: publish_settings type ( fpm_export_settings ) , allocatable :: export_settings type ( version_t ) :: version character ( len = :), allocatable :: common_args , compiler_args , run_args , working_dir , & & c_compiler , cxx_compiler , archiver , version_s , token_s character ( len =* ), parameter :: fc_env = \"FC\" , cc_env = \"CC\" , ar_env = \"AR\" , & & fflags_env = \"FFLAGS\" , cflags_env = \"CFLAGS\" , cxxflags_env = \"CXXFLAGS\" , ldflags_env = \"LDFLAGS\" , & & fc_default = \"gfortran\" , cc_default = \" \" , ar_default = \" \" , flags_default = \" \" , & & cxx_env = \"CXX\" , cxx_default = \" \" type ( error_t ), allocatable :: error call set_help () os = get_os_type () ! text for --version switch, select case ( os ) case ( OS_LINUX ); os_type = \"OS Type: Linux\" case ( OS_MACOS ); os_type = \"OS Type: macOS\" case ( OS_WINDOWS ); os_type = \"OS Type: Windows\" case ( OS_CYGWIN ); os_type = \"OS Type: Cygwin\" case ( OS_SOLARIS ); os_type = \"OS Type: Solaris\" case ( OS_FREEBSD ); os_type = \"OS Type: FreeBSD\" case ( OS_OPENBSD ); os_type = \"OS Type: OpenBSD\" case ( OS_UNKNOWN ); os_type = \"OS Type: Unknown\" case default ; os_type = \"OS Type: UNKNOWN\" end select ! Get current release version version = fpm_version () version_s = version % s () version_text = [ character ( len = 80 ) :: & & 'Version: ' // trim ( version_s ) // ', alpha' , & & 'Program: fpm(1)' , & & 'Description: A Fortran package manager and build system' , & & 'Home Page: https://github.com/fortran-lang/fpm' , & & 'License: MIT' , & & os_type ] ! find the subcommand name by looking for first word on command ! not starting with dash CLI_RESPONSE_FILE = . true . cmdarg = get_subcommand () common_args = & ' --directory:C \" \"' // & ' --verbose F' run_args = & ' --target \" \"' // & ' --list F' // & ' --runner \" \"' // & ' --runner-args \" \"' compiler_args = & ' --profile \" \"' // & ' --no-prune F' // & ' --compiler \"' // get_fpm_env ( fc_env , fc_default ) // '\"' // & ' --c-compiler \"' // get_fpm_env ( cc_env , cc_default ) // '\"' // & ' --cxx-compiler \"' // get_fpm_env ( cxx_env , cxx_default ) // '\"' // & ' --archiver \"' // get_fpm_env ( ar_env , ar_default ) // '\"' // & ' --flag:: \"' // get_fpm_env ( fflags_env , flags_default ) // '\"' // & ' --c-flag:: \"' // get_fpm_env ( cflags_env , flags_default ) // '\"' // & ' --cxx-flag:: \"' // get_fpm_env ( cxxflags_env , flags_default ) // '\"' // & ' --link-flag:: \"' // get_fpm_env ( ldflags_env , flags_default ) // '\"' ! now set subcommand-specific help text and process commandline ! arguments. Then call subcommand routine select case ( trim ( cmdarg )) case ( 'run' ) call set_args ( common_args // compiler_args // run_args // '& & --all F & & --example F& & --' , help_run , version_text ) call check_build_vals () if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif if ( specified ( 'target' ) ) then call split ( sget ( 'target' ), tnames , delimiters = ' ,:' ) names = [ character ( len = max ( len ( names ), len ( tnames ))) :: names , tnames ] endif ! convert --all to '*' if ( lget ( 'all' )) then names = [ character ( len = max ( len ( names ), 1 )) :: names , '*' ] endif ! convert special string '..' to equivalent (shorter) '*' ! to allow for a string that does not require shift-key and quoting do i = 1 , size ( names ) if ( names ( i ) == '..' ) names ( i ) = '*' enddo ! If there are additional command-line arguments, remove the additional ! double quotes which have been added by M_CLI2 val_runner_args = sget ( 'runner-args' ) call remove_characters_in_set ( val_runner_args , set = '\"' ) c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( fpm_run_settings :: cmd_settings ) val_runner = sget ( 'runner' ) if ( specified ( 'runner' ) . and . val_runner == '' ) val_runner = 'echo' cmd_settings = fpm_run_settings (& & args = remaining ,& & profile = val_profile ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & example = lget ( 'example' ), & & list = lget ( 'list' ),& & build_tests = . false .,& & name = names ,& & runner = val_runner ,& & runner_args = val_runner_args , & & verbose = lget ( 'verbose' ) ) case ( 'build' ) call set_args ( common_args // compiler_args // '& & --list F & & --show-model F & & --dump \" \" & & --tests F & & --' , help_build , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) val_dump = sget ( 'dump' ) if ( specified ( 'dump' ) . and . val_dump == '' ) val_dump = 'fpm_model.toml' allocate ( fpm_build_settings :: cmd_settings ) cmd_settings = fpm_build_settings ( & & profile = val_profile ,& & dump = val_dump ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & list = lget ( 'list' ),& & show_model = lget ( 'show-model' ),& & build_tests = lget ( 'tests' ),& & verbose = lget ( 'verbose' ) ) case ( 'new' ) call set_args ( common_args // '& & --src F & & --lib F & & --app F & & --test F & & --example F & & --backfill F & & --full F & & --bare F' , & & help_new , version_text ) select case ( size ( unnamed )) case ( 1 ) if ( lget ( 'backfill' )) then name = '.' else write ( stderr , '(*(7x,g0,/))' ) & & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]|[--full|--bare] [--backfill]' call fpm_stop ( 1 , 'directory name required' ) endif case ( 2 ) name = trim ( unnamed ( 2 )) case default write ( stderr , '(7x,g0)' ) & & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]| [--full|--bare] [--backfill]' call fpm_stop ( 2 , 'only one directory name allowed' ) end select !*! canon_path is not converting \".\", etc. if ( name == '.' ) then call get_current_directory ( name , error ) if ( allocated ( error )) then write ( stderr , '(\"[Error]\", 1x, a)' ) error % message stop 1 endif endif name = canon_path ( name ) if ( . not . is_fortran_name ( to_fortran_name ( basename ( name ))) ) then write ( stderr , '(g0)' ) [ character ( len = 72 ) :: & & ' the fpm project name must be made of up to 63 ASCII letters,' , & & ' numbers, underscores, or hyphens, and start with a letter.' ] call fpm_stop ( 4 , ' ' ) endif allocate ( fpm_new_settings :: cmd_settings ) if ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' , 'bare' ])) & & . and . lget ( 'full' ) ) then write ( stderr , '(*(a))' )& & ' --full and any of [--src|--lib,--app,--test,--example,--bare]' , & & ' are mutually exclusive.' call fpm_stop ( 5 , ' ' ) elseif ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' , 'full' ])) & & . and . lget ( 'bare' ) ) then write ( stderr , '(*(a))' )& & ' --bare and any of [--src|--lib,--app,--test,--example,--full]' , & & ' are mutually exclusive.' call fpm_stop ( 3 , ' ' ) elseif ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' ]) ) ) then cmd_settings = fpm_new_settings (& & backfill = lget ( 'backfill' ), & & name = name , & & with_executable = lget ( 'app' ), & & with_lib = any ([ lget ( 'lib' ), lget ( 'src' )]), & & with_test = lget ( 'test' ), & & with_example = lget ( 'example' ), & & verbose = lget ( 'verbose' ) ) else ! default if no specific directories are requested cmd_settings = fpm_new_settings (& & backfill = lget ( 'backfill' ) , & & name = name , & & with_executable = . true ., & & with_lib = . true ., & & with_test = . true ., & & with_example = lget ( 'full' ), & & with_full = lget ( 'full' ), & & with_bare = lget ( 'bare' ), & & verbose = lget ( 'verbose' ) ) endif case ( 'help' , 'manual' ) call set_args ( common_args , help_help , version_text ) if ( size ( unnamed ) < 2 ) then if ( unnamed ( 1 ) == 'help' ) then unnamed = [ ' ' , 'fpm' ] else unnamed = manual endif elseif ( unnamed ( 2 ) == 'manual' ) then unnamed = manual endif allocate ( character ( len = widest ) :: help_text ( 0 )) do i = 2 , size ( unnamed ) select case ( unnamed ( i )) case ( ' ' ) case ( 'fpm ' ) help_text = [ character ( len = widest ) :: help_text , help_fpm ] case ( 'new ' ) help_text = [ character ( len = widest ) :: help_text , help_new ] case ( 'build ' ) help_text = [ character ( len = widest ) :: help_text , help_build ] case ( 'install' ) help_text = [ character ( len = widest ) :: help_text , help_install ] case ( 'run ' ) help_text = [ character ( len = widest ) :: help_text , help_run ] case ( 'test ' ) help_text = [ character ( len = widest ) :: help_text , help_test ] case ( 'runner' ) help_text = [ character ( len = widest ) :: help_text , help_runner ] case ( 'list ' ) help_text = [ character ( len = widest ) :: help_text , help_list ] case ( 'update ' ) help_text = [ character ( len = widest ) :: help_text , help_update ] case ( 'help ' ) help_text = [ character ( len = widest ) :: help_text , help_help ] case ( 'version' ) help_text = [ character ( len = widest ) :: help_text , version_text ] case ( 'clean' ) help_text = [ character ( len = widest ) :: help_text , help_clean ] case ( 'publish' ) help_text = [ character ( len = widest ) :: help_text , help_publish ] case default help_text = [ character ( len = widest ) :: help_text , & & ' unknown help topic \"' // trim ( unnamed ( i )) // '\"' ] !!& ' unknown help topic \"'//trim(unnamed(i)).'not found in:',manual] end select enddo call printhelp ( help_text ) case ( 'install' ) call set_args ( common_args // compiler_args // '& & --no-rebuild F --prefix \" \" & & --list F & & --libdir \"lib\" --bindir \"bin\" --includedir \"include\"' , & help_install , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( install_settings , source = fpm_install_settings (& list = lget ( 'list' ), & profile = val_profile ,& prune = . not . lget ( 'no-prune' ), & compiler = val_compiler , & c_compiler = c_compiler , & cxx_compiler = cxx_compiler , & archiver = archiver , & flag = val_flag , & cflag = val_cflag , & cxxflag = val_cxxflag , & ldflag = val_ldflag , & no_rebuild = lget ( 'no-rebuild' ), & verbose = lget ( 'verbose' ))) call get_char_arg ( install_settings % prefix , 'prefix' ) call get_char_arg ( install_settings % libdir , 'libdir' ) call get_char_arg ( install_settings % bindir , 'bindir' ) call get_char_arg ( install_settings % includedir , 'includedir' ) call move_alloc ( install_settings , cmd_settings ) case ( 'list' ) call set_args ( common_args // '& & --list F& &' , help_list , version_text ) if ( lget ( 'list' )) then help_text = [ character ( widest ) :: help_list_nodash , help_list_dash ] else help_text = help_list_nodash endif call printhelp ( help_text ) case ( 'test' ) call set_args ( common_args // compiler_args // run_args // ' --' , & help_test , version_text ) call check_build_vals () if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif if ( specified ( 'target' ) ) then call split ( sget ( 'target' ), tnames , delimiters = ' ,:' ) names = [ character ( len = max ( len ( names ), len ( tnames ))) :: names , tnames ] endif ! convert special string '..' to equivalent (shorter) '*' ! to allow for a string that does not require shift-key and quoting do i = 1 , size ( names ) if ( names ( i ) == '..' ) names ( i ) = '*' enddo ! If there are additional command-line arguments, remove the additional ! double quotes which have been added by M_CLI2 val_runner_args = sget ( 'runner-args' ) call remove_characters_in_set ( val_runner_args , set = '\"' ) c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( fpm_test_settings :: cmd_settings ) val_runner = sget ( 'runner' ) if ( specified ( 'runner' ) . and . val_runner == '' ) val_runner = 'echo' cmd_settings = fpm_test_settings (& & args = remaining , & & profile = val_profile , & & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & example = . false ., & & list = lget ( 'list' ), & & build_tests = . true ., & & name = names , & & runner = val_runner , & & runner_args = val_runner_args , & & verbose = lget ( 'verbose' )) case ( 'update' ) call set_args ( common_args // ' --fetch-only F --clean F --dump \" \" ' , & help_update , version_text ) if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif val_dump = sget ( 'dump' ) if ( specified ( 'dump' ) . and . val_dump == '' ) val_dump = 'fpm_dependencies.toml' allocate ( fpm_update_settings :: cmd_settings ) cmd_settings = fpm_update_settings ( name = names , dump = val_dump , & fetch_only = lget ( 'fetch-only' ), verbose = lget ( 'verbose' ), & clean = lget ( 'clean' )) case ( 'export' ) call set_args ( common_args // compiler_args // '& & --manifest \"filename\" & & --model \"filename\" & & --dependencies \"filename\" ' , & help_build , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( export_settings , source = fpm_export_settings (& profile = val_profile ,& prune = . not . lget ( 'no-prune' ), & compiler = val_compiler , & c_compiler = c_compiler , & cxx_compiler = cxx_compiler , & archiver = archiver , & flag = val_flag , & cflag = val_cflag , & show_model = . true ., & cxxflag = val_cxxflag , & ldflag = val_ldflag , & verbose = lget ( 'verbose' ))) call get_char_arg ( export_settings % dump_model , 'model' ) call get_char_arg ( export_settings % dump_manifest , 'manifest' ) call get_char_arg ( export_settings % dump_dependencies , 'dependencies' ) call move_alloc ( export_settings , cmd_settings ) case ( 'clean' ) call set_args ( common_args // & & ' --registry-cache' // & & ' --skip' // & & ' --all' , & help_clean , version_text ) block logical :: skip , clean_all skip = lget ( 'skip' ) clean_all = lget ( 'all' ) if ( all ([ skip , clean_all ])) then call fpm_stop ( 6 , 'Do not specify both --skip and --all options on the clean subcommand.' ) end if allocate ( fpm_clean_settings :: cmd_settings ) cmd_settings = fpm_clean_settings ( & & registry_cache = lget ( 'registry-cache' ), & & clean_skip = skip , & & clean_all = clean_all ) end block case ( 'publish' ) call set_args ( common_args // compiler_args // '& & --show-package-version F & & --show-upload-data F & & --dry-run F & & --token \" \" & & --list F & & --show-model F & & --tests F & & --' , help_publish , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) token_s = sget ( 'token' ) allocate ( fpm_publish_settings :: cmd_settings ) cmd_settings = fpm_publish_settings ( & & show_package_version = lget ( 'show-package-version' ), & & show_upload_data = lget ( 'show-upload-data' ), & & is_dry_run = lget ( 'dry-run' ), & & profile = val_profile ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & list = lget ( 'list' ),& & show_model = lget ( 'show-model' ),& & build_tests = lget ( 'tests' ),& & verbose = lget ( 'verbose' ),& & token = token_s ) case default if ( cmdarg . ne . '' . and . which ( 'fpm-' // cmdarg ). ne . '' ) then call run ( 'fpm-' // trim ( cmdarg ) // ' ' // get_command_arguments_quoted (),. false .) stop else call set_args ( '& & --list F& &' , help_fpm , version_text ) ! Note: will not get here if --version or --usage or --help ! is present on commandline if ( lget ( 'list' )) then help_text = help_list_dash elseif ( len_trim ( cmdarg ) == 0 ) then write ( stdout , '(*(a))' ) 'Fortran Package Manager:' write ( stdout , '(*(a))' ) ' ' help_text = [ character ( widest ) :: help_list_nodash , help_usage ] else write ( stderr , '(*(a))' ) ' unknown subcommand [' , & & trim ( cmdarg ), ']' help_text = [ character ( widest ) :: help_list_dash , help_usage ] endif call printhelp ( help_text ) endif end select if ( allocated ( cmd_settings )) then working_dir = sget ( \"directory\" ) call move_alloc ( working_dir , cmd_settings % working_dir ) end if contains subroutine check_build_vals () val_compiler = sget ( 'compiler' ) if ( val_compiler == '' ) val_compiler = 'gfortran' val_flag = \" \" // sget ( 'flag' ) val_cflag = \" \" // sget ( 'c-flag' ) val_cxxflag = \" \" // sget ( 'cxx-flag' ) val_ldflag = \" \" // sget ( 'link-flag' ) val_profile = sget ( 'profile' ) end subroutine check_build_vals !> Print help text and stop subroutine printhelp ( lines ) character ( len = :), intent ( in ), allocatable :: lines (:) integer :: iii , ii if ( allocated ( lines )) then ii = size ( lines ) if ( ii > 0 . and . len ( lines ) > 0 ) then write ( stdout , '(g0)' )( trim ( lines ( iii )), iii = 1 , ii ) else write ( stdout , '(a)' ) ' *printhelp* output requested is empty' endif endif stop end subroutine printhelp end subroutine get_command_line_settings subroutine set_help () help_list_nodash = [ character ( len = 80 ) :: & 'USAGE: fpm [ SUBCOMMAND [SUBCOMMAND_OPTIONS] ]|[--list|--help|--version]' , & ' where SUBCOMMAND is commonly new|build|run|test ' , & ' ' , & ' subcommand may be one of ' , & ' ' , & ' build Compile the package placing results in the \"build\" directory' , & ' help Display help ' , & ' list Display this list of subcommand descriptions ' , & ' new Create a new Fortran package directory with sample files ' , & ' run Run the local package application programs ' , & ' test Run the test programs ' , & ' update Update and manage project dependencies ' , & ' install Install project ' , & ' clean Delete the build ' , & ' publish Publish package to the registry ' , & ' ' , & ' Enter \"fpm --list\" for a brief list of subcommand options. Enter ' , & ' \"fpm --help\" or \"fpm SUBCOMMAND --help\" for detailed descriptions. ' , & ' ' ] help_list_dash = [ character ( len = 80 ) :: & ' ' , & ' build [--compiler COMPILER_NAME] [--profile PROF] [--flag FFLAGS] [--list] ' , & ' [--tests] [--no-prune] [--dump [FILENAME]] ' , & ' help [NAME(s)] ' , & ' new NAME [[--lib|--src] [--app] [--test] [--example]]| ' , & ' [--full|--bare][--backfill] ' , & ' update [NAME(s)] [--fetch-only] [--clean] [--verbose] [--dump [FILENAME]] ' , & ' list [--list] ' , & ' run [[--target] NAME(s) [--example] [--profile PROF] [--flag FFLAGS] [--all] ' , & ' [--runner \"CMD\"] [--compiler COMPILER_NAME] [--list] [-- ARGS] ' , & ' test [[--target] NAME(s)] [--profile PROF] [--flag FFLAGS] [--runner \"CMD\"] ' , & ' [--list] [--compiler COMPILER_NAME] [-- ARGS] ' , & ' install [--profile PROF] [--flag FFLAGS] [--no-rebuild] [--prefix PATH] ' , & ' [options] ' , & ' clean [--skip] [--all] [--registry-cache] ' , & ' publish [--token TOKEN] [--show-package-version] [--show-upload-data] ' , & ' [--dry-run] [--verbose] ' , & ' ' ] help_usage = [ character ( len = 80 ) :: & '' ] help_runner = [ character ( len = 80 ) :: & 'NAME ' , & ' --runner(1) - a shared option for specifying an application to launch ' , & ' executables. ' , & ' ' , & 'SYNOPSIS ' , & ' fpm run|test --runner CMD ... --runner-args ARGS -- SUFFIX_OPTIONS ' , & ' ' , & 'DESCRIPTION ' , & ' The --runner option allows specifying a program to launch ' , & ' executables selected via the fpm(1) subcommands \"run\" and \"test\". This ' , & ' gives easy recourse to utilities such as debuggers and other tools ' , & ' that wrap other executables. ' , & ' ' , & ' These external commands are not part of fpm(1) itself as they vary ' , & ' from platform to platform or require independent installation. ' , & ' ' , & 'OPTION ' , & ' --runner ''CMD'' quoted command used to launch the fpm(1) executables. ' , & ' Available for both the \"run\" and \"test\" subcommands. ' , & ' If the keyword is specified without a value the default command ' , & ' is \"echo\". ' , & ' --runner-args \"args\" an additional option to pass command-line arguments ' , & ' to the runner command, instead of to the fpm app. ' , & ' -- SUFFIX_OPTIONS additional options to suffix the command CMD and executable ' , & ' file names with. These options are passed as command-line ' , & ' arguments to the app. ' , & 'EXAMPLES ' , & ' Use cases for ''fpm run|test --runner \"CMD\"'' include employing ' , & ' the following common GNU/Linux and Unix commands: ' , & ' ' , & ' INTERROGATE ' , & ' + nm - list symbols from object files ' , & ' + size - list section sizes and total size. ' , & ' + ldd - print shared object dependencies ' , & ' + ls - list directory contents ' , & ' + stat - display file or file system status ' , & ' + file - determine file type ' , & ' PERFORMANCE AND DEBUGGING ' , & ' + gdb - The GNU Debugger ' , & ' + valgrind - a suite of tools for debugging and profiling ' , & ' + time - time a simple command or give resource usage ' , & ' + timeout - run a command with a time limit ' , & ' COPY ' , & ' + install - copy files and set attributes ' , & ' + tar - an archiving utility ' , & ' ALTER ' , & ' + rm - remove files or directories ' , & ' + chmod - change permissions of a file ' , & ' + strip - remove unnecessary information from strippable files ' , & ' ' , & ' For example ' , & ' ' , & ' fpm test --runner gdb ' , & ' fpm run --runner \"tar cvfz $HOME/bundle.tgz\" ' , & ' fpm run --runner \"mpiexec\" --runner-args \"-np 12\" ' , & ' fpm run --runner ldd ' , & ' fpm run --runner strip ' , & ' fpm run --runner ''cp -t /usr/local/bin'' ' , & ' ' , & ' # options after executable name can be specified after the -- option ' , & ' fpm --runner cp run -- /usr/local/bin/ ' , & ' # generates commands of the form \"cp $FILENAME /usr/local/bin/\" ' , & ' ' , & ' # bash(1) alias example: ' , & ' alias fpm-install=\\ ' , & ' \"fpm run --profile release --runner ''install -vbp -m 0711 -t ~/.local/bin''\" ' , & ' fpm-install ' , & '' ] help_fpm = [ character ( len = 80 ) :: & 'NAME ' , & ' fpm(1) - A Fortran package manager and build system ' , & ' ' , & 'SYNOPSIS ' , & ' fpm SUBCOMMAND [SUBCOMMAND_OPTIONS] ' , & ' ' , & ' fpm --help|--version|--list ' , & ' ' , & 'DESCRIPTION ' , & ' fpm(1) is a package manager that helps you create Fortran projects ' , & ' from source -- it automatically determines dependencies! ' , & ' ' , & ' Most significantly fpm(1) lets you draw upon other fpm(1) packages ' , & ' in distributed git(1) repositories as if the packages were a basic ' , & ' part of your default programming environment, as well as letting ' , & ' you share your projects with others in a similar manner. ' , & ' ' , & ' All output goes into the directory \"build/\" which can generally be ' , & ' removed and rebuilt if required. Note that if external packages are ' , & ' being used you need network connectivity to rebuild from scratch. ' , & ' ' , & 'SUBCOMMANDS ' , & ' Valid fpm(1) subcommands are: ' , & ' ' , & ' + build Compile the packages into the \"build/\" directory. ' , & ' + new Create a new Fortran package directory with sample files. ' , & ' + update Update the project dependencies. ' , & ' + run Run the local package binaries. Defaults to all binaries ' , & ' for that release. ' , & ' + test Run the tests. ' , & ' + help Alternate to the --help switch for displaying help text. ' , & ' + list Display brief descriptions of all subcommands. ' , & ' + install Install project. ' , & ' + clean Delete directories in the \"build/\" directory, except ' , & ' dependencies. Prompts for confirmation to delete. ' , & ' + publish Publish package to the registry. ' , & ' ' , & ' Their syntax is ' , & ' ' , & ' build [--profile PROF] [--flag FFLAGS] [--list] [--compiler COMPILER_NAME] ' , & ' [--tests] [--no-prune] [--dump [FILENAME]] ' , & ' new NAME [[--lib|--src] [--app] [--test] [--example]]| ' , & ' [--full|--bare][--backfill] ' , & ' update [NAME(s)] [--fetch-only] [--clean] [--dump [FILENAME]] ' , & ' run [[--target] NAME(s)] [--profile PROF] [--flag FFLAGS] [--list] [--all] ' , & ' [--example] [--runner \"CMD\"] [--compiler COMPILER_NAME] ' , & ' [--no-prune] [-- ARGS] ' , & ' test [[--target] NAME(s)] [--profile PROF] [--flag FFLAGS] [--list] ' , & ' [--runner \"CMD\"] [--compiler COMPILER_NAME] [--no-prune] [-- ARGS] ' , & ' help [NAME(s)] ' , & ' list [--list] ' , & ' install [--profile PROF] [--flag FFLAGS] [--no-rebuild] [--prefix PATH] ' , & ' [options] ' , & ' clean [--skip] [--all] [--registry-cache] ' , & ' publish [--token TOKEN] [--show-package-version] [--show-upload-data] ' , & ' [--dry-run] [--verbose] ' , & ' ' , & 'SUBCOMMAND OPTIONS ' , & ' -C, --directory PATH' , & ' Change working directory to PATH before running any command' , & help_text_build_common , & help_text_compiler , & help_text_flag , & ' --list List candidates instead of building or running them. On ' , & ' the fpm(1) command this shows a brief list of subcommands.' , & ' --runner CMD Provides a command to prefix program execution paths. ' , & ' -- ARGS Arguments to pass to executables. ' , & ' --skip Delete directories in the build/ directory without ' , & ' prompting, but skip dependencies. Cannot be used together ' , & ' with --all. ' , & ' --all Delete directories in the build/ directory without ' , & ' prompting, including dependencies. Cannot be used together' , & ' with --skip. ' , & ' --registry-cache Delete registry cache. ' , & ' ' , & 'VALID FOR ALL SUBCOMMANDS ' , & ' --help Show help text and exit ' , & ' --verbose Display additional information when available ' , & ' --version Show version information and exit. ' , & ' ' , & '@file ' , & ' You may replace the default options for the fpm(1) command from a ' , & ' file if your first options begin with @file. Initial options will ' , & ' then be read from the \"response file\" \"file.rsp\" in the current ' , & ' directory. ' , & ' ' , & ' If \"file\" does not exist or cannot be read, then an error occurs and' , & ' the program stops. Each line of the file is prefixed with \"options\" ' , & ' and interpreted as a separate argument. The file itself may not ' , & ' contain @file arguments. That is, it is not processed recursively. ' , & ' ' , & ' For more information on response files see ' , & ' ' , & ' https://urbanjost.github.io/M_CLI2/set_args.3m_cli2.html ' , & ' ' , & ' The basic functionality described here will remain the same, but ' , & ' other features described at the above reference may change. ' , & ' ' , & ' An example file: ' , & ' ' , & ' # my build options ' , & ' options build ' , & ' options --compiler gfortran ' , & ' options --flag \"-pg -static -pthread -Wunreachable-code -Wunused ' , & ' -Wuninitialized -g -O -fbacktrace -fdump-core -fno-underscoring ' , & ' -frecord-marker=4 -L/usr/X11R6/lib -L/usr/X11R6/lib64 -lX11\" ' , & ' ' , & ' Note --flag would have to be on one line as response files do not ' , & ' (currently) allow for continued lines or multiple specifications of ' , & ' the same option. ' , & ' ' , & help_text_environment , & ' ' , & 'EXAMPLES ' , & ' sample commands: ' , & ' ' , & ' fpm new mypackage --app --test ' , & ' fpm build ' , & ' fpm test ' , & ' fpm run ' , & ' fpm run --example ' , & ' fpm new --help ' , & ' fpm run myprogram --profile release -- -x 10 -y 20 --title \"my title\" ' , & ' fpm install --prefix ~/.local ' , & ' fpm clean --all ' , & ' ' , & 'SEE ALSO ' , & ' ' , & ' + The fpm(1) home page is at https://github.com/fortran-lang/fpm ' , & ' + Registered fpm(1) packages are at https://fortran-lang.org/packages ' , & ' + The fpm(1) TOML file format is described at ' , & ' https://fpm.fortran-lang.org/spec/manifest.html ' , & '' ] help_list = [ character ( len = 80 ) :: & 'NAME ' , & ' list(1) - list summary of fpm(1) subcommands ' , & ' ' , & 'SYNOPSIS ' , & ' fpm list ' , & ' ' , & ' fpm list --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' Display a short description for each fpm(1) subcommand. ' , & ' ' , & 'OPTIONS ' , & ' --list display a list of command options as well. This is the ' , & ' same output as generated by \"fpm --list\". ' , & ' ' , & 'EXAMPLES ' , & ' display a short list of fpm(1) subcommands ' , & ' ' , & ' fpm list ' , & ' fpm --list ' , & '' ] help_run = [ character ( len = 80 ) :: & 'NAME ' , & ' run(1) - the fpm(1) subcommand to run project applications ' , & ' ' , & 'SYNOPSIS ' , & ' fpm run [[--target] NAME(s) [--profile PROF] [--flag FFLAGS]' , & ' [--compiler COMPILER_NAME] [--runner \"CMD\"] [--example]' , & ' [--list] [--all] [-- ARGS]' , & ' ' , & ' fpm run --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' Run the applications in your fpm(1) package. By default applications ' , & ' in /app or specified as \"executable\" in your \"fpm.toml\" manifest are ' , & ' used. Alternatively demonstration programs in example/ or specified in' , & ' the \"example\" section in \"fpm.toml\" can be executed. The applications ' , & ' are automatically rebuilt before being run if they are out of date. ' , & ' ' , & 'OPTIONS ' , & ' --target NAME(s) list of application names to execute. No name is ' , & ' required if only one target exists. If no name is ' , & ' supplied and more than one candidate exists or a ' , & ' name has no match a list is produced and fpm(1) ' , & ' exits. ' , & ' ' , & ' Basic \"globbing\" is supported where \"?\" represents ' , & ' any single character and \"*\" represents any string. ' , & ' Note The glob string normally needs quoted to ' , & ' the special characters from shell expansion. ' , & ' --all Run all examples or applications. An alias for --target ''*''. ' , & ' --example Run example programs instead of applications. ' , & help_text_build_common , & help_text_compiler , & help_text_flag , & ' --runner CMD A command to prefix the program execution paths with. ' , & ' see \"fpm help runner\" for further details. ' , & ' --list list basenames of candidates instead of running them. Note ' , & ' out-of-date candidates will still be rebuilt before being ' , & ' listed. ' , & ' -- ARGS optional arguments to pass to the program(s). The same ' , & ' arguments are passed to all program names specified. ' , & ' ' , & help_text_environment , & ' ' , & 'EXAMPLES ' , & ' fpm(1) - run or display project applications: ' , & ' ' , & ' fpm run # run a target when only one exists or list targets ' , & ' fpm run --list # list basename of all targets, running nothing. ' , & ' fpm run \"demo*\" --list # list target basenames starting with \"demo*\".' , & ' fpm run \"psi*\" --runner # list target pathnames starting with \"psi*\".' , & ' fpm run --all # run all targets, no matter how many there are. ' , & ' ' , & ' # run default program built or to be built with the compiler command ' , & ' # \"f90\". If more than one app exists a list displays and target names' , & ' # are required. ' , & ' fpm run --compiler f90 ' , & ' ' , & ' # run example programs instead of the application programs. ' , & ' fpm run --example \"*\" ' , & ' ' , & ' # run a specific program and pass arguments to the command ' , & ' fpm run myprog -- -x 10 -y 20 --title \"my title line\" ' , & ' ' , & ' # run production version of two applications ' , & ' fpm run --target prg1,prg2 --profile release ' , & ' ' , & ' # install executables in directory (assuming install(1) exists) ' , & ' fpm run --runner ''install -b -m 0711 -p -t /usr/local/bin'' ' , & '' ] help_build = [ character ( len = 80 ) :: & 'NAME ' , & ' build(1) - the fpm(1) subcommand to build a project ' , & ' ' , & 'SYNOPSIS ' , & ' fpm build [--profile PROF] [--flag FFLAGS] [--compiler COMPILER_NAME] ' , & ' [--list] [--tests] [--dump [FILENAME]] ' , & ' ' , & ' fpm build --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' The \"fpm build\" command ' , & ' o Fetches any dependencies ' , & ' o Scans your sources ' , & ' o Builds them in the proper order ' , & ' ' , & ' The Fortran source files are assumed by default to be in ' , & ' o src/ for modules and procedure source ' , & ' o app/ main program(s) for applications ' , & ' o test/ main program(s) and support files for project tests ' , & ' o example/ main program(s) for example programs ' , & ' Changed or new files found are rebuilt. The results are placed in ' , & ' the build/ directory. ' , & ' ' , & ' Non-default pathnames and remote dependencies are used if ' , & ' specified in the \"fpm.toml\" file. ' , & ' ' , & 'OPTIONS ' , & help_text_build_common ,& help_text_compiler , & help_text_flag , & ' --list list candidates instead of building or running them ' , & ' --tests build all tests (otherwise only if needed) ' , & ' --show-model show the model and exit (do not build) ' , & ' --dump [FILENAME] save model representation to file. use JSON format ' , & ' if file name is *.json; use TOML format otherwise ' , & ' (default file name: model.toml) ' , & ' --help print this help and exit ' , & ' --version print program version information and exit ' , & ' ' , & help_text_environment , & ' ' , & 'EXAMPLES ' , & ' Sample commands: ' , & ' ' , & ' fpm build # build with debug options ' , & ' fpm build --profile release # build with high optimization ' , & '' ] help_help = [ character ( len = 80 ) :: & 'NAME ' , & ' help(1) - the fpm(1) subcommand to display help ' , & ' ' , & 'SYNOPSIS ' , & ' fpm help [fpm] [new] [build] [run] [test] [help] [version] [manual] ' , & ' [runner] ' , & ' ' , & 'DESCRIPTION ' , & ' The \"fpm help\" command is an alternative to the --help parameter ' , & ' on the fpm(1) command and its subcommands. ' , & ' ' , & 'OPTIONS ' , & ' NAME(s) A list of topic names to display. All the subcommands ' , & ' have their own page (new, build, run, test, ...). ' , & ' ' , & ' The special name \"manual\" displays all the fpm(1) ' , & ' built-in documentation. ' , & ' ' , & ' The default is to display help for the fpm(1) command ' , & ' itself. ' , & ' ' , & 'EXAMPLES ' , & ' Sample usage: ' , & ' ' , & ' fpm help # general fpm(1) command help ' , & ' fpm help version # show program version ' , & ' fpm help new # display help for \"new\" subcommand ' , & ' fpm help manual # All fpm(1) built-in documentation ' , & ' ' , & '' ] help_new = [ character ( len = 80 ) :: & 'NAME ' , & ' new(1) - the fpm(1) subcommand to initialize a new project ' , & ' ' , & 'SYNOPSIS ' , & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]| ' , & ' [--full|--bare][--backfill] ' , & ' fpm new --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' \"fpm new\" creates and populates a new programming project directory. ' , & ' ' , & ' It ' , & ' o creates a directory with the specified name ' , & ' o runs the command \"git init\" in that directory ' , & ' o populates the directory with the default project directories ' , & ' o adds sample Fortran source files ' , & ' ' , & ' The default file structure (that will be automatically scanned) is ' , & ' ' , & ' NAME/ ' , & ' fpm.toml ' , & ' src/ ' , & ' NAME.f90 ' , & ' app/ ' , & ' main.f90 ' , & ' test/ ' , & ' check.f90 ' , & ' example/ ' , & ' demo.f90 ' , & ' ' , & ' Using this file structure is highly encouraged, particularly for ' , & ' small packages primarily intended to be used as dependencies. ' , & ' ' , & ' If you find this restrictive and need to customize the package ' , & ' structure you will find using the --full switch creates a ' , & ' heavily annotated manifest file with references to documentation ' , & ' to aid in constructing complex package structures. ' , & ' ' , & ' Remember to update the information in the sample \"fpm.toml\" ' , & ' file with your name and e-mail address. ' , & ' ' , & 'OPTIONS ' , & ' NAME the name of the project directory to create. The name ' , & ' must be made of up to 63 ASCII letters, digits, underscores, ' , & ' or hyphens, and start with a letter. ' , & ' ' , & ' The default is to create the src/, app/, and test/ directories. ' , & ' If any of the following options are specified then only the ' , & ' selected subdirectories are generated: ' , & ' ' , & ' --lib,--src create directory src/ and a placeholder module ' , & ' named \"NAME.f90\" for use with subcommand \"build\". ' , & ' --app create directory app/ and a placeholder main ' , & ' program for use with subcommand \"run\". ' , & ' --test create directory test/ and a placeholder program ' , & ' for use with the subcommand \"test\". Note that sans ' , & ' \"--lib\" it really does not have anything to test. ' , & ' --example create directory example/ and a placeholder program ' , & ' for use with the subcommand \"run --example\". ' , & ' It is only created by default if \"--full is\" specified. ' , & ' ' , & ' So the default is equivalent to ' ,& ' ' , & ' fpm NAME --lib --app --test ' , & ' ' , & ' --backfill By default the directory must not exist. If this ' , & ' option is present the directory may pre-exist and ' , & ' only subdirectories and files that do not ' , & ' already exist will be created. For example, if you ' , & ' previously entered \"fpm new myname --lib\" entering ' , & ' \"fpm new myname -full --backfill\" will create any missing' , & ' app/, example/, and test/ directories and programs. ' , & ' ' , & ' --full By default a minimal manifest file (\"fpm.toml\") is ' , & ' created that depends on auto-discovery. With this ' , & ' option a much more extensive manifest sample is written ' , & ' and the example/ directory is created and populated. ' , & ' It is designed to facilitate creating projects that ' , & ' depend extensively on non-default build options. ' , & ' ' , & ' --bare A minimal manifest file (\"fpm.toml\") is created and ' , & ' \"README.md\" file is created but no directories or ' , & ' sample Fortran are generated. ' , & ' ' , & ' --help print this help and exit ' , & ' --version print program version information and exit ' , & ' ' , & 'EXAMPLES ' , & ' Sample use ' , & ' ' , & ' fpm new myproject # create new project directory and seed it ' , & ' cd myproject # Enter the new directory ' , & ' # and run commands such as ' , & ' fpm build ' , & ' fpm run # run lone example application program ' , & ' fpm test # run example test program(s) ' , & ' fpm run --example # run lone example program ' , & ' ' , & ' fpm new A --full # create example/ and an annotated fpm.toml as well' , & ' fpm new A --bare # create no directories ' , & ' create any missing files in current directory ' , & ' fpm new --full --backfill ' , & '' ] help_test = [ character ( len = 80 ) :: & 'NAME ' , & ' test(1) - the fpm(1) subcommand to run project tests ' , & ' ' , & 'SYNOPSIS ' , & ' fpm test [[--target] NAME(s)] [--profile PROF] [--flag FFLAGS]' , & ' [--compiler COMPILER_NAME ] [--runner \"CMD\"] [--list][-- ARGS]' , & ' ' , & ' fpm test --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' Run applications you have built to test your project. ' , & ' ' , & 'OPTIONS ' , & ' --target NAME(s) optional list of specific test names to execute. ' , & ' The default is to run all the tests in test/ ' , & ' or the tests listed in the \"fpm.toml\" file. ' , & ' ' , & ' Basic \"globbing\" is supported where \"?\" represents ' , & ' any single character and \"*\" represents any string. ' , & ' Note The glob string normally needs quoted to ' , & ' protect the special characters from shell expansion.' , & help_text_build_common ,& help_text_compiler , & help_text_flag , & ' --runner CMD A command to prefix the program execution paths with. ' , & ' see \"fpm help runner\" for further details. ' , & ' --list list candidate basenames instead of running them. Note they' , & ' --list will still be built if not currently up to date. ' , & ' -- ARGS optional arguments to pass to the test program(s). ' , & ' The same arguments are passed to all test names ' , & ' specified. ' , & ' ' , & help_text_environment , & ' ' , & 'EXAMPLES ' , & 'run tests ' , & ' ' , & ' # run default tests in /test or as specified in \"fpm.toml\" ' , & ' fpm test ' , & ' ' , & ' # run using compiler command \"f90\" ' , & ' fpm test --compiler f90 ' , & ' ' , & ' # run a specific test and pass arguments to the command ' , & ' fpm test mytest -- -x 10 -y 20 --title \"my title line\" ' , & ' ' , & ' fpm test tst1 tst2 --profile PROF # run production version of two tests' , & '' ] help_update = [ character ( len = 80 ) :: & 'NAME' , & ' update(1) - manage project dependencies' , & '' , & 'SYNOPSIS' , & ' fpm update [--fetch-only] [--clean] [--verbose] [--dump [FILENAME]] [NAME(s)]' , & '' , & 'DESCRIPTION' , & ' Manage and update project dependencies. If no dependency names are' , & ' provided all the dependencies are updated automatically.' , & '' , & 'OPTIONS' , & ' --fetch-only Only fetch dependencies, do not update existing projects' , & ' --clean Do not use previous dependency cache' , & ' --verbose Show additional printout' , & ' --dump [FILENAME] Dump updated dependency tree to file. use JSON format ' , & ' if file name is *.json; use TOML format otherwise ' , & ' (default file name: fpm_dependencies.toml) ' , & '' , & 'SEE ALSO' , & ' The fpm(1) home page at https://github.com/fortran-lang/fpm' , & '' ] help_install = [ character ( len = 80 ) :: & 'NAME' , & ' install(1) - install fpm projects' , & '' , & 'SYNOPSIS' , & ' fpm install [--profile PROF] [--flag FFLAGS] [--list] [--no-rebuild]' , & ' [--prefix DIR] [--bindir DIR] [--libdir DIR] [--includedir DIR]' , & ' [--verbose]' , & '' , & 'DESCRIPTION' , & ' Subcommand to install fpm projects. Running install will export the' , & ' current project to the selected prefix, this will by default install all' , & ' executables (tests and examples are excluded) which are part of the projects.' , & ' Libraries and module files are only installed for projects requiring the' , & ' installation of those components in the package manifest.' , & '' , & 'OPTIONS' , & ' --list list all installable targets for this project,' , & ' but do not install any of them' , & help_text_build_common ,& help_text_flag , & ' --no-rebuild do not rebuild project before installation' , & ' --prefix DIR path to installation directory (requires write access),' , & ' the default prefix on Unix systems is $HOME/.local' , & ' and %APPDATA%\\local on Windows' , & ' --bindir DIR subdirectory to place executables in (default: bin)' , & ' --libdir DIR subdirectory to place libraries and archives in' , & ' (default: lib)' , & ' --includedir DIR subdirectory to place headers and module files in' , & ' (default: include)' , & ' --verbose print more information' , & '' , & help_text_environment , & '' , & 'EXAMPLES' , & ' 1. Install release version of project:' , & '' , & ' fpm install --profile release' , & '' , & ' 2. Install the project without rebuilding the executables:' , & '' , & ' fpm install --no-rebuild' , & '' , & ' 3. Install executables to a custom prefix into the exe directory:' , & '' , & ' fpm install --prefix $PWD --bindir exe' , & '' ] help_clean = [ character ( len = 80 ) :: & 'NAME' , & ' clean(1) - delete the build' , & '' , & 'SYNOPSIS' , & ' fpm clean' , & '' , & 'DESCRIPTION' , & ' Prompts the user to confirm deletion of the build. If affirmative,' , & ' directories in the build/ directory are deleted, except dependencies.' , & ' Use the --registry-cache option to delete the registry cache.' , & '' , & 'OPTIONS' , & ' --skip Delete the build without prompting but skip dependencies.' , & ' --all Delete the build without prompting including dependencies.' , & ' --registry-cache Delete registry cache.' , & '' ] help_publish = [ character ( len = 80 ) :: & 'NAME' , & ' publish(1) - publish package to the registry' , & '' , & 'SYNOPSIS' , & ' fpm publish [--token TOKEN] [--show-package-version] [--show-upload-data]' , & ' [--dry-run] [--verbose] ' , & '' , & ' fpm publish --help|--version' , & '' , & 'DESCRIPTION' , & ' Follow the steps to create a tarball and upload a package to the registry:' , & '' , & ' 1. Register on the website (https://registry-phi.vercel.app/).' , & ' 2. Create a namespace. Uploaded packages must be assigned to a unique' , & ' namespace to avoid conflicts among packages with similar names. A' , & ' namespace can accommodate multiple packages.' , & ' 3. Create a token for that namespace. A token is linked to your username' , & ' and is used to authenticate you during the upload process. Do not share' , & ' the token with others.' , & ' 4. Run fpm publish --token TOKEN to upload the package to the registry.' , & ' But be aware that the upload is permanent. An uploaded package cannot be' , & ' deleted.' , & '' , & ' See documentation for more information regarding package upload and usage:' , & '' , & ' Package upload:' , & ' https://fpm.fortran-lang.org/spec/publish.html' , & '' , & ' Package usage:' , & ' https://fpm.fortran-lang.org/spec/manifest.html#dependencies-from-a-registry' , & '' , & 'OPTIONS' , & ' --show-package-version show package version without publishing' , & ' --show-upload-data show upload data without publishing' , & ' --dry-run perform dry run without publishing' , & ' --help print this help and exit' , & ' --version print program version information and exit' , & ' --verbose print more information' , & '' , & 'EXAMPLES' , & '' , & ' fpm publish --show-package-version # show package version without publishing' , & ' fpm publish --show-upload-data # show upload data without publishing' , & ' fpm publish --token TOKEN --dry-run # perform dry run without publishing' , & ' fpm publish --token TOKEN # upload package to the registry' , & '' ] end subroutine set_help subroutine get_char_arg ( var , arg ) character ( len = :), allocatable , intent ( out ) :: var character ( len =* ), intent ( in ) :: arg var = sget ( arg ) if ( len_trim ( var ) == 0 ) deallocate ( var ) end subroutine get_char_arg !> Get an environment variable for fpm, this routine ensures that every variable !> used by fpm is prefixed with FPM_. function get_fpm_env ( env , default ) result ( val ) character ( len =* ), intent ( in ) :: env character ( len =* ), intent ( in ) :: default character ( len = :), allocatable :: val character ( len =* ), parameter :: fpm_prefix = \"FPM_\" val = get_env ( fpm_prefix // env , default ) end function get_fpm_env !> Build a full runner command (executable + command-line arguments) function runner_command ( cmd ) result ( run_cmd ) class ( fpm_run_settings ), intent ( in ) :: cmd character ( len = :), allocatable :: run_cmd !> Get executable if ( len_trim ( cmd % runner ) > 0 ) then run_cmd = trim ( cmd % runner ) else run_cmd = '' end if !> Append command-line arguments if ( len_trim ( cmd % runner_args ) > 0 ) run_cmd = run_cmd // ' ' // trim ( cmd % runner_args ) end function runner_command !> Check name in list ID. return 0 if not found integer function name_ID ( cmd , name ) class ( fpm_run_settings ), intent ( in ) :: cmd character ( * ), intent ( in ) :: name integer :: j !> Default: not found name_ID = 0 if (. not . allocated ( cmd % name )) return do j = 1 , size ( cmd % name ) if ( glob ( trim ( name ), trim ( cmd % name ( j )))) then name_ID = j return end if end do end function name_ID end module fpm_command_line","tags":"","loc":"sourcefile/fpm_command_line.f90.html"},{"title":"new.f90 – Fortran-lang/fpm","text":"Source Code module fpm_cmd_new !># Definition of the \"new\" subcommand !> !> A type of the general command base class [[fpm_cmd_settings]] !> was created for the \"new\" subcommand ==> type [[fpm_new_settings]]. !> This procedure read the values that were set on the command line !> from this type to decide what actions to take. !> !> It is virtually self-contained and so independant of the rest of the !> application that it could function as a separate program. !> !> The \"new\" subcommand options currently consist of a SINGLE top !> directory name to create that must have a name that is an !> allowable Fortran variable name. That should have been ensured !> by the command line processing before this procedure is called. !> So basically this routine has already had the options vetted and !> just needs to conditionally create a few files. !> !> As described in the documentation it will selectively !> create the subdirectories app/, test/, src/, and example/ !> and populate them with sample files. !> !> It also needs to create an initial manifest file \"fpm.toml\". !> !> It then calls the system command \"git init\". !> !> It should test for file existence and not overwrite existing !> files and inform the user if there were conflicts. !> !> Any changes should be reflected in the documentation in !> [[fpm_command_line.f90]] !> !> FUTURE !> A filename like \".\" would need system commands or a standard routine !> like realpath(3c) to process properly. !> !> Perhaps allow more than one name on a single command. It is an arbitrary !> restriction based on a concensus preference, not a required limitation. !> !> Initially the name of the directory is used as the module name in the !> src file so it must be an allowable Fortran variable name. If there are !> complaints about it it might be changed. Handling unicode at this point !> might be problematic as not all current compilers handle it. Other !> utilities like content trackers (ie. git) or repositories like github !> might also have issues with alternative names or names with spaces, etc. !> So for the time being it seems prudent to encourage simple ASCII top directory !> names (similiar to the primary programming language Fortran itself). !> !> Should be able to create or pull more complicated initial examples !> based on various templates. It should place or mention other relevant !> documents such as a description of the manifest file format in user hands; !> or how to access registered packages and local packages, !> although some other command might provide that (and the help command should !> be the first go-to for a CLI utility). use fpm_command_line , only : fpm_new_settings use fpm_environment , only : OS_LINUX , OS_MACOS , OS_WINDOWS use fpm_filesystem , only : join_path , exists , basename , mkdir , is_dir use fpm_filesystem , only : fileopen , fileclose , warnwrite , which , run use fpm_strings , only : join , to_fortran_name use fpm_error , only : fpm_stop use , intrinsic :: iso_fortran_env , only : stderr => error_unit implicit none private public :: cmd_new contains subroutine cmd_new ( settings ) type ( fpm_new_settings ), intent ( in ) :: settings integer , parameter :: tfc = selected_char_kind ( 'DEFAULT' ) character ( len = :, kind = tfc ), allocatable :: bname ! baeename of NAME character ( len = :, kind = tfc ), allocatable :: tomlfile (:) character ( len = :, kind = tfc ), allocatable :: littlefile (:) !> TOP DIRECTORY NAME PROCESSING !> see if requested new directory already exists and process appropriately if ( exists ( settings % name ) . and . . not . settings % backfill ) then write ( stderr , '(*(g0,1x))' )& & '' , settings % name , 'already exists.' write ( stderr , '(*(g0,1x))' )& & ' perhaps you wanted to add --backfill ?' return elseif ( is_dir ( settings % name ) . and . settings % backfill ) then write ( * , '(*(g0))' ) 'backfilling ' , settings % name elseif ( exists ( settings % name ) ) then write ( stderr , '(*(g0,1x))' )& & '' , settings % name , 'already exists and is not a directory.' return else ! make new directory call mkdir ( settings % name ) endif !> temporarily change to new directory as a test. NB: System dependent call run ( 'cd ' // settings % name ) ! NOTE: need some system routines to handle filenames like \".\" ! like realpath() or getcwd(). bname = basename ( settings % name ) littlefile = [ character ( len = 80 ) :: '# ' // bname , 'My cool new project!' ] ! create NAME/README.md call warnwrite ( join_path ( settings % name , 'README.md' ), littlefile ) ! start building NAME/fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: & & ' # This is your fpm(Fortran Package Manager) manifest file ' ,& & ' # (\"fpm.toml\"). It is heavily annotated to help guide you though ' ,& & ' # customizing a package build, although the defaults are sufficient ' ,& & ' # for many basic packages. ' ,& & ' # ' ,& & ' # The manifest file is not only used to provide metadata identifying ' ,& & ' # your project (so it can be used by others as a dependency). It can ' ,& & ' # specify where your library and program sources live, what the name ' ,& & ' # of the executable(s) will be, what files to build, dependencies on ' ,& & ' # other fpm packages, and what external libraries are required. ' ,& & ' # ' ,& & ' # The manifest format must conform to the TOML configuration file ' ,& & ' # standard. ' ,& & ' # ' ,& & ' # TOML files support flexible use of white-space and commenting of the ' ,& & ' # configuration data, but for clarity in this sample active directives ' ,& & ' # begin in column one. Inactive example directives are commented ' ,& & ' # out with a pound character (\"#\") but begin in column one as well. ' ,& & ' # Commentary begins with a pound character in column three. ' ,& & ' # ' ,& & ' # This file draws heavily upon the following references: ' ,& & ' # ' ,& & ' # The fpm home page at ' ,& & ' # https://github.com/fortran-lang/fpm ' ,& & ' # A complete list of keys and their attributes at ' ,& & ' # https://github.com/fortran-lang/fpm/blob/main/manifest-reference.md ' ,& & ' # examples of fpm project packaging at ' ,& & ' # https://github.com/fortran-lang/fpm/blob/main/PACKAGING.md ' ,& & ' # The Fortran TOML file interface and it''s references at ' ,& & ' # https://github.com/toml-f/toml-f ' ,& & ' # ' ,& & ' #----------------------- ' ,& & ' # project Identification ' ,& & ' #----------------------- ' ,& & ' # We begin with project metadata at the manifest root. This data is designed ' ,& & ' # to aid others when searching for the project in a repository and to ' ,& & ' # identify how and when to contact the package supporters. ' ,& & ' ' ,& & 'name = \"' // bname // '\"' ,& & ' # The project name (required) is how the project will be referred to. ' ,& & ' # The name is used by other packages using it as a dependency. It also ' ,& & ' # is used as the default name of any library built and the optional ' ,& & ' # default executable built from app/main.f90. It must conform to the rules ' ,& & ' # for a Fortran variable name. ' ,& & ' ' ,& & 'version = \"0.1.0\" ' ,& & ' # The project version number is a string. A recommended scheme for ' ,& & ' # specifying versions is the Semantic Versioning scheme. ' ,& & ' ' ,& & 'license = \"license\" ' ,& & ' # Licensing information specified using SPDX identifiers is preferred ' ,& & ' # (eg. \"Apache-2.0 OR MIT\" or \"LGPL-3.0-or-later\"). ' ,& & ' ' ,& & 'maintainer = \"jane.doe@example.com\" ' ,& & ' # Information on the project maintainer and means to reach out to them. ' ,& & ' ' ,& & 'author = \"Jane Doe\" ' ,& & ' # Information on the project author. ' ,& & ' ' ,& & 'copyright = \"Copyright 2020 Jane Doe\" ' ,& & ' # A statement clarifying the Copyright status of the project. ' ,& & ' ' ,& & '#description = \"A short project summary in plain text\" ' ,& & ' # The description provides a short summary on the project. It should be ' ,& & ' # plain text and not use any markup formatting. ' ,& & ' ' ,& & '#categories = [\"fortran\", \"graphics\"] ' ,& & ' # Categories associated with the project. Listing only one is preferred. ' ,& & ' ' ,& & '#keywords = [\"hdf5\", \"mpi\"] ' ,& & ' # The keywords field is an array of strings describing the project. ' ,& & ' ' ,& & '#homepage = \"https://stdlib.fortran-lang.org\" ' ,& & ' # URL to the webpage of the project. ' ,& & ' ' ,& & ' # ----------------------------------------- ' ,& & ' # We are done with identifying the project. ' ,& & ' # ----------------------------------------- ' ,& & ' # ' ,& & ' # Now lets start describing how the project should be built. ' ,& & ' # ' ,& & ' # Note tables would go here but we will not be talking about them (much)!!' ,& & ' # ' ,& & ' # Tables are a way to explicitly specify large numbers of programs in ' ,& & ' # a compact format instead of individual per-program entries in the ' ,& & ' # [[executable]], [[test]], and [[example]] sections to follow but ' ,& & ' # will not be discussed further except for the following notes: ' ,& & ' # ' ,& & ' # + Tables must appear (here) before any sections are declared. Once a ' ,& & ' # section is specified in a TOML file everything afterwards must be ' ,& & ' # values for that section or the beginning of a new section. A simple ' ,& & ' # example looks like: ' ,& & ' ' ,& & '#executable = [ ' ,& & '# { name = \"a-prog\" }, ' ,& & '# { name = \"app-tool\", source-dir = \"tool\" }, ' ,& & '# { name = \"fpm-man\", source-dir = \"tool\", main=\"fman.f90\" } ' ,& & '#] ' ,& & ' ' ,& & ' # This would be in lieue of the [[executable]] section found later in this ' ,& & ' # configuration file. ' ,& & ' # + See the reference documents (at the beginning of this document) ' ,& & ' # for more information on tables if you have long lists of programs ' ,& & ' # to build and are not simply depending on auto-detection. ' ,& & ' # ' ,& & ' # Now lets begin the TOML sections (lines beginning with \"[\") ... ' ,& & ' # ' ,& & ' ' ,& & '[install] # Options for the \"install\" subcommand ' ,& & ' ' ,& & ' # When you run the \"install\" subcommand only executables are installed by ' ,& & ' # default on the local system. Library projects that will be used outside of ' ,& & ' # \"fpm\" can set the \"library\" boolean to also allow installing the module ' ,& & ' # files and library archive. Without this being set to \"true\" an \"install\" ' ,& & ' # subcommand ignores parameters that specify library installation. ' ,& & ' ' ,& & 'library = false ' ,& & ' ' ,& & '[build] # General Build Options ' ,& & ' ' ,& & ' ### Automatic target discovery ' ,& & ' # ' ,& & ' # Normally fpm recursively searches the app/, example/, and test/ directories ' ,& & ' # for program sources and builds them. To disable this automatic discovery of ' ,& & ' # program targets set the following to \"false\": ' ,& & ' ' ,& & '#auto-executables = true ' ,& & '#auto-examples = true ' ,& & '#auto-tests = true ' ,& & ' ' ,& & ' ### Package-level External Library Links ' ,& & ' # ' ,& & ' # To declare link-time dependencies on external libraries a list of ' ,& & ' # native libraries can be specified with the \"link\" entry. You may ' ,& & ' # have one library name or a list of strings in case several ' ,& & ' # libraries should be linked. This list of library dependencies is ' ,& & ' # exported to dependent packages. You may have to alter your library ' ,& & ' # search-path to ensure the libraries can be accessed. Typically, ' ,& & ' # this is done with the LD_LIBRARY_PATH environment variable on ULS ' ,& & ' # (Unix-Like Systems). You only specify the core name of the library ' ,& & ' # (as is typical with most programming environments, where you ' ,& & ' # would specify \"-lz\" on your load command to link against the zlib ' ,& & ' # compression library even though the library file would typically be ' ,& & ' # a file called \"libz.a\" \"or libz.so\"). So to link against that library ' ,& & ' # you would specify: ' ,& & ' ' ,& & '#link = \"z\" ' ,& & ' ' ,& & ' # Note that in some cases the order of the libraries matters: ' ,& & ' ' ,& & '#link = [\"blas\", \"lapack\"] ' ,& & '' ] endif if ( settings % with_bare ) then elseif ( settings % with_lib ) then call mkdir ( join_path ( settings % name , 'src' ) ) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & '[library] ' ,& & ' ' ,& & ' # You can change the name of the directory to search for your library ' ,& & ' # source from the default of \"src/\". Library targets are exported ' ,& & ' # and usable by other projects. ' ,& & ' ' ,& & 'source-dir=\"src\" ' ,& & ' ' ,& & ' # this can be a list: ' ,& & ' ' ,& & '#source-dir=[\"src\", \"src2\"] ' ,& & ' ' ,& & ' # More complex libraries may organize their modules in subdirectories. ' ,& & ' # For modules in a top-level directory fpm requires (but does not ' ,& & ' # enforce) that: ' ,& & ' # ' ,& & ' # + The module has the same name as the source file. This is important. ' ,& & ' # + There should be only one module per file. ' ,& & ' # ' ,& & ' # These two requirements simplify the build process for fpm. As Fortran ' ,& & ' # compilers emit module files (.mod) with the same name as the module ' ,& & ' # itself (but not the source file, .f90), naming the module the same ' ,& & ' # as the source file allows fpm to: ' ,& & ' # ' ,& & ' # + Uniquely and exactly map a source file (.f90) to its object (.o) ' ,& & ' # and module (.mod) files. ' ,& & ' # + Avoid conflicts with modules of the same name that could appear ' ,& & ' # in dependency packages. ' ,& & ' # ' ,& & ' ### Multi-level library source ' ,& & ' # You can place your module source files in any number of levels of ' ,& & ' # subdirectories inside your source directory, but there are certain naming ' ,& & ' # conventions to be followed -- module names must contain the path components ' ,& & ' # of the directory that its source file is in. ' ,& & ' # ' ,& & ' # This rule applies generally to any number of nested directories and ' ,& & ' # modules. For example, src/a/b/c/d.f90 must define a module called a_b_c_d. ' ,& & ' # Again, this is not enforced but may be required in future releases. ' ,& & '' ] endif ! create placeholder module src/bname.f90 littlefile = [ character ( len = 80 ) :: & & 'module ' // to_fortran_name ( bname ), & & ' implicit none' , & & ' private' , & & '' , & & ' public :: say_hello' , & & 'contains' , & & ' subroutine say_hello' , & & ' print *, \"Hello, ' // bname // '!\"' , & & ' end subroutine say_hello' , & & 'end module ' // to_fortran_name ( bname )] ! create NAME/src/NAME.f90 call warnwrite ( join_path ( settings % name , 'src' , bname // '.f90' ),& & littlefile ) endif if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile ,& & '[dependencies] ' ,& & ' ' ,& & ' # Inevitably, you will want to be able to include other packages in ' ,& & ' # a project. Fpm makes this incredibly simple, by taking care of ' ,& & ' # fetching and compiling your dependencies for you. You just tell it ' ,& & ' # what your dependencies names are, and where to find them. ' ,& & ' # ' ,& & ' # If you are going to distribute your package only place dependencies ' ,& & ' # here someone using your package as a remote dependency needs built. ' ,& & ' # You can define dependencies just for developer executables in the ' ,& & ' # next section, or even for specific executables as we will see below ' ,& & ' # (Then fpm will still fetch and compile it when building your ' ,& & ' # developer executables, but users of your library will not have to). ' ,& & ' # ' ,& & ' ## GLOBAL DEPENDENCIES (exported with your project) ' ,& & ' # ' ,& & ' # Typically, dependencies are defined by specifying the project''s ' ,& & ' # git repository. ' ,& & ' # ' ,& & ' # You can be specific about which version of a dependency you would ' ,& & ' # like. By default the latest default branch is used. You can ' ,& & ' # optionally specify a branch, a tag or a commit value. ' ,& & ' # ' ,& & ' # So here are several alternates for specifying a remote dependency (you ' ,& & ' # can have at most one of \"branch\", \"rev\" or \"tag\" present): ' ,& & ' ' ,& & '#stdlib = { git = \"https://github.com/LKedward/stdlib-fpm.git\" } ' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\",branch = \"master\" },' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\", tag = \"v0.1.0\" }, ' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\", rev = \"5a9b7a8\" }. ' ,& & ' ' ,& & ' # There may be multiple packages listed: ' ,& & ' ' ,& & '#M_strings = { git = \"https://github.com/urbanjost/M_strings.git\" } ' ,& & '#M_time = { git = \"https://github.com/urbanjost/M_time.git\" } ' ,& & ' ' ,& & ' # ' ,& & ' # You can even specify the local path to another project if it is in ' ,& & ' # a sub-folder (If for example you have got another fpm package **in ' ,& & ' # the same repository**) like this: ' ,& & ' ' ,& & '#M_strings = { path = \"M_strings\" } ' ,& & ' ' ,& & ' # This tells fpm that we depend on a crate called M_strings which is found ' ,& & ' # in the M_strings folder (relative to the fpm.toml it’s written in). ' ,& & ' # ' ,& & ' # For a more verbose layout use normal tables rather than inline tables ' ,& & ' # to specify dependencies: ' ,& & ' ' ,& & '#[dependencies.toml-f] ' ,& & '#git = \"https://github.com/toml-f/toml-f\" ' ,& & '#rev = \"2f5eaba864ff630ba0c3791126a3f811b6e437f3\" ' ,& & ' ' ,& & ' # Now you can use any modules from these libraries anywhere in your ' ,& & ' # code -- whether is in your library source or a program source. ' ,& & ' ' ,& & '[dev-dependencies] ' ,& & ' ' ,& & ' ## Dependencies Only for Development ' ,& & ' # ' ,& & ' # You can specify dependencies your library or application does not ' ,& & ' # depend on in a similar way. The difference is that these will not ' ,& & ' # be exported as part of your project to those using it as a remote ' ,& & ' # dependency. ' ,& & ' # ' ,& & ' # Currently, like a global dependency it will still be available for ' ,& & ' # all codes. It is up to the developer to ensure that nothing except ' ,& & ' # developer test programs rely upon it. ' ,& & ' ' ,& & '#M_msg = { git = \"https://github.com/urbanjost/M_msg.git\" } ' ,& & '#M_verify = { git = \"https://github.com/urbanjost/M_verify.git\" } ' ,& & '' ] endif if ( settings % with_bare ) then elseif ( settings % with_executable ) then ! create next section of fpm.toml call mkdir ( join_path ( settings % name , 'app' )) ! create NAME/app or stop if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & ' #----------------------------------- ' ,& & ' ## Application-specific declarations ' ,& & ' #----------------------------------- ' ,& & ' # Now lets begin entries for the TOML tables (lines beginning with \"[[\") ' ,& & ' # that describe the program sources -- applications, tests, and examples. ' ,& & ' # ' ,& & ' # First we will configuration individual applications run with \"fpm run\". ' ,& & ' # ' ,& & ' # + the \"name\" entry for the executable to be built must always ' ,& & ' # be specified. The name must satisfy the rules for a Fortran ' ,& & ' # variable name. This will be the name of the binary installed by ' ,& & ' # the \"install\" subcommand and used on the \"run\" subcommand. ' ,& & ' # + The source directory for each executable can be adjusted by the ' ,& & ' # \"source-dir\" entry. ' ,& & ' # + The basename of the source file containing the program body can ' ,& & ' # be specified with the \"main\" entry. ' ,& & ' # + Executables can also specify their own external package and ' ,& & ' # library link dependencies. ' ,& & ' # ' ,& & ' # Currently, like a global dependency any external package dependency ' ,& & ' # will be available for all codes. It is up to the developer to ensure ' ,& & ' # that nothing except the application programs specified rely upon it. ' ,& & ' # ' ,& & ' # Note if your application needs to use a module internally, but you do not ' ,& & ' # intend to build it as a library to be used in other projects, you can ' ,& & ' # include the module in your program source file or directory as well. ' ,& & ' ' ,& & '[[executable]] ' ,& & 'name=\"' // bname // '\"' ,& & 'source-dir=\"app\" ' ,& & 'main=\"main.f90\" ' ,& & ' ' ,& & ' # You may repeat this pattern to define additional applications. For instance,' ,& & ' # the following sample illustrates all accepted options, where \"link\" and ' ,& & ' # \"executable.dependencies\" keys are the same as the global external library ' ,& & ' # links and package dependencies described previously except they apply ' ,& & ' # only to this executable: ' ,& & ' ' ,& & '#[[ executable ]] ' ,& & '#name = \"app-name\" ' ,& & '#source-dir = \"prog\" ' ,& & '#main = \"program.f90\" ' ,& & '#link = \"z\" ' ,& & '#[executable.dependencies] ' ,& & '#M_CLI = { git = \"https://github.com/urbanjost/M_CLI.git\" } ' ,& & '#helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } ' ,& & '#M_path = { git = \"https://github.com/urbanjost/M_path.git\" } ' ,& & '' ] endif if ( exists ( bname // '/src/' )) then littlefile = [ character ( len = 80 ) :: & & 'program main' , & & ' use ' // to_fortran_name ( bname ) // ', only: say_hello' , & & ' implicit none' , & & '' , & & ' call say_hello()' , & & 'end program main' ] else littlefile = [ character ( len = 80 ) :: & & 'program main' , & & ' implicit none' , & & '' , & & ' print *, \"hello from project ' // bname // '\"' , & & 'end program main' ] endif call warnwrite ( join_path ( settings % name , 'app/main.f90' ), littlefile ) endif if ( settings % with_bare ) then elseif ( settings % with_test ) then ! create NAME/test or stop call mkdir ( join_path ( settings % name , 'test' )) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile ,& & '[[test]] ' ,& & ' ' ,& & ' # The same declarations can be made for test programs, which are ' ,& & ' # executed with the \"fpm test\" command and are not build when your ' ,& & ' # package is used as a dependency by other packages. These are ' ,& & ' # typically unit tests of the package only used during package ' ,& & ' # development. ' ,& & ' ' ,& & 'name=\"runTests\" ' ,& & 'source-dir=\"test\" ' ,& & 'main=\"check.f90\" ' ,& & ' ' ,& & ' # you may repeat this pattern to add additional explicit test program ' ,& & ' # parameters. The following example contains a sample of all accepted ' ,& & ' # options. ' ,& & ' ' ,& & '#[[ test ]] ' ,& & '#name = \"tester\" ' ,& & '#source-dir=\"test\" ' ,& & '#main=\"tester.f90\" ' ,& & '#link = [\"blas\", \"lapack\"] ' ,& & '#[test.dependencies] ' ,& & '#M_CLI2 = { git = \"https://github.com/urbanjost/M_CLI2.git\" } ' ,& & '#M_io = { git = \"https://github.com/urbanjost/M_io.git\" } ' ,& & '#M_system= { git = \"https://github.com/urbanjost/M_system.git\" } ' ,& & '' ] endif littlefile = [ character ( len = 80 ) :: & & 'program check' , & & 'implicit none' , & & '' , & & 'print *, \"Put some tests in here!\"' , & & 'end program check' ] ! create NAME/test/check.f90 call warnwrite ( join_path ( settings % name , 'test/check.f90' ), littlefile ) endif if ( settings % with_bare ) then elseif ( settings % with_example ) then ! create NAME/example or stop call mkdir ( join_path ( settings % name , 'example' )) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & '[[example]] ' ,& & ' ' ,& & ' # Example applications for a project are defined here. ' ,& & ' # These are run via \"fpm run --example NAME\" and like the ' ,& & ' # test applications, are not built when this package is used as a ' ,& & ' # dependency by other packages. ' ,& & ' ' ,& & 'name=\"demo\" ' ,& & 'source-dir=\"example\" ' ,& & 'main=\"demo.f90\" ' ,& & ' ' ,& & ' # ' ,& & ' # you may add additional programs to the example table. The following ' ,& & ' # example contains a sample of all accepted options ' ,& & ' ' ,& & '#[[ example ]] ' ,& & '#name = \"example-tool\" ' ,& & '#source-dir=\"example\" ' ,& & '#main=\"tool.f90\" ' ,& & '#link = \"z\" ' ,& & '#[example.dependencies] ' ,& & '#M_kracken95 = { git = \"https://github.com/urbanjost/M_kracken95.git\" } ' ,& & '#datetime = {git = \"https://github.com/wavebitscientific/datetime-fortran.git\" }' ,& & '' ] endif littlefile = [ character ( len = 80 ) :: & & 'program demo' , & & 'implicit none' , & & '' , & & 'print *, \"Put some examples in here!\"' , & & 'end program demo' ] ! create NAME/example/demo.f90 call warnwrite ( join_path ( settings % name , 'example/demo.f90' ), littlefile ) endif ! now that built it write NAME/fpm.toml if ( allocated ( tomlfile ) ) then call validate_toml_data ( tomlfile ) call warnwrite ( join_path ( settings % name , 'fpm.toml' ), tomlfile ) else call create_verified_basic_manifest ( join_path ( settings % name , 'fpm.toml' )) endif ! assumes git(1) is installed and in path if ( which ( 'git' ) /= '' ) then call run ( 'git init ' // settings % name ) endif contains function git_metadata ( what ) result ( returned ) !> get metadata values such as email address and git name from git(1) or return appropriate default use fpm_filesystem , only : get_temp_filename , getline character ( len =* ), intent ( in ) :: what ! keyword designating what git metatdata to query character ( len = :), allocatable :: returned ! value to return for requested keyword character ( len = :), allocatable :: command character ( len = :), allocatable :: temp_filename character ( len = :), allocatable :: iomsg character ( len = :), allocatable :: temp_value integer :: stat , unit temp_filename = get_temp_filename () ! for known keywords set default value for RETURNED and associated git(1) command for query select case ( what ) case ( 'uname' ) returned = \"Jane Doe\" command = \"git config --get user.name > \" // temp_filename case ( 'email' ) returned = \"jane.doe@example.com\" command = \"git config --get user.email > \" // temp_filename case default write ( stderr , '(*(g0,1x))' )& & ' *git_metadata* unknown metadata name ' , trim ( what ) returned = '' return end select ! Execute command if git(1) is in command path if ( which ( 'git' ) /= '' ) then call run ( command , exitstat = stat ) if ( stat /= 0 ) then ! If command failed just return default return else ! Command did not return an error so try to read expected output file open ( file = temp_filename , newunit = unit , iostat = stat ) if ( stat == 0 ) then ! Read file into a scratch variable until status of doing so is checked call getline ( unit , temp_value , stat , iomsg ) if ( stat == 0 . and . temp_value /= '' ) then ! Return output from successful command returned = temp_value endif endif ! Always do the CLOSE because a failed open has unpredictable results. ! Add IOSTAT so a failed close does not cause program to stop close ( unit , status = \"delete\" , iostat = stat ) endif endif end function git_metadata subroutine create_verified_basic_manifest ( filename ) !> create a basic but verified default manifest file use fpm_toml , only : toml_table , toml_serialize , set_value use fpm_manifest_package , only : package_config_t , new_package use fpm_error , only : error_t implicit none character ( len =* ), intent ( in ) :: filename type ( toml_table ) :: table type ( package_config_t ) :: package type ( error_t ), allocatable :: error integer :: lun character ( len = 8 ) :: date character (:), allocatable :: output if ( exists ( filename )) then write ( stderr , '(*(g0,1x))' ) ' ' , filename ,& & 'already exists. Not overwriting' return endif !> get date to put into metadata in manifest file \"fpm.toml\" call date_and_time ( DATE = date ) table = toml_table () call fileopen ( filename , lun ) ! fileopen stops on error call set_value ( table , \"name\" , BNAME ) call set_value ( table , \"version\" , \"0.1.0\" ) call set_value ( table , \"license\" , \"license\" ) call set_value ( table , \"author\" , git_metadata ( 'uname' )) call set_value ( table , \"maintainer\" , git_metadata ( 'email' )) call set_value ( table , \"copyright\" , 'Copyright ' // date ( 1 : 4 ) // ', ' // git_metadata ( 'uname' )) ! continue building of manifest ! ... call new_package ( package , table , error = error ) if ( allocated ( error )) call fpm_stop ( 3 , '' ) output = toml_serialize ( table ) if ( settings % verbose ) then print '(a)' , output endif write ( lun , '(a)' ) output call fileclose ( lun ) ! fileopen stops on error end subroutine create_verified_basic_manifest subroutine validate_toml_data ( input ) !> verify a string array is a valid fpm.toml file ! use tomlf , only : toml_load use fpm_toml , only : toml_table , toml_serialize implicit none character ( kind = tfc , len = :), intent ( in ), allocatable :: input (:) character ( len = 1 ), parameter :: nl = new_line ( 'a' ) type ( toml_table ), allocatable :: table character ( kind = tfc , len = :), allocatable :: joined_string ! you have to add a newline character by using the intrinsic ! function `new_line(\"a\")` to get the lines processed correctly. joined_string = join ( input , right = nl ) if ( allocated ( table )) deallocate ( table ) call toml_load ( table , joined_string ) if ( allocated ( table )) then if ( settings % verbose ) then ! If the TOML file is successfully parsed the table will be allocated and ! can be written by `toml_serialize` to the standard output print '(a)' , toml_serialize ( table ) endif call table % destroy endif end subroutine validate_toml_data end subroutine cmd_new end module fpm_cmd_new","tags":"","loc":"sourcefile/new.f90.html"},{"title":"meta.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the metapackage configuration data. !> !> A metapackage table can currently have the following fields !> !>```toml !>[metapackages] !>fpm = \"0.1.0\" !>openmp = bool !>stdlib = bool !>``` module fpm_manifest_metapackages use fpm_error , only : error_t , fatal_error , syntax_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value use fpm_environment implicit none private public :: metapackage_config_t , new_meta_config , is_meta_package public :: metapackage_request_t , new_meta_request !> Configuration data for a single metapackage request type :: metapackage_request_t !> Request flag logical :: on = . false . !> Metapackage name character ( len = :), allocatable :: name !> Version Specification string character ( len = :), allocatable :: version end type metapackage_request_t !> Configuration data for metapackages type :: metapackage_config_t !> Request MPI support type ( metapackage_request_t ) :: mpi !> Request OpenMP support type ( metapackage_request_t ) :: openmp !> Request stdlib support type ( metapackage_request_t ) :: stdlib !> fortran-lang minpack type ( metapackage_request_t ) :: minpack !> HDF5 type ( metapackage_request_t ) :: hdf5 end type metapackage_config_t contains !> Destroy a metapackage request elemental subroutine request_destroy ( self ) !> Instance of the request class ( metapackage_request_t ), intent ( inout ) :: self self % on = . false . if ( allocated ( self % version )) deallocate ( self % version ) if ( allocated ( self % name )) deallocate ( self % name ) end subroutine request_destroy !> Parse version string of a metapackage request subroutine request_parse ( self , version_request , error ) ! Instance of this metapackage type ( metapackage_request_t ), intent ( inout ) :: self ! Parse version request character ( len =* ), intent ( in ) :: version_request ! Error message type ( error_t ), allocatable , intent ( out ) :: error ! wildcard = use any versions if ( version_request == \"*\" ) then ! Any version is OK self % on = . true . self % version = version_request else call fatal_error ( error , 'Value <' // version_request // '> for metapackage ' // self % name // & 'is not currently supported. Try \"*\" instead. ' ) return end if end subroutine request_parse !> Construct a new metapackage request from the dependencies table subroutine new_meta_request ( self , key , table , meta_allowed , error ) type ( metapackage_request_t ), intent ( out ) :: self !> The package name character ( len =* ), intent ( in ) :: key !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys allowed to be metapackages logical , intent ( in ), optional :: meta_allowed (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , i character ( len = :), allocatable :: value logical , allocatable :: allow_meta (:) type ( toml_key ), allocatable :: keys (:) call request_destroy ( self ) !> Set name self % name = key if (. not . is_meta_package ( key )) then call fatal_error ( error , \"Error reading fpm.toml: <\" // key // \"> is not a valid metapackage name\" ) return end if !> The toml table is not checked here because it already passed !> the \"new_dependencies\" check call table % get_keys ( keys ) !> Set list of entries that are allowed to be metapackages if ( present ( meta_allowed )) then if ( size ( meta_allowed ) /= size ( keys )) then call fatal_error ( error , \"Internal error: list of metapackage-enable entries does not match table size\" ) return end if allow_meta = meta_allowed else allocate ( allow_meta ( size ( keys )), source = . true .) endif do i = 1 , size ( keys ) ! Skip standard dependencies if (. not . allow_meta ( i )) cycle if ( keys ( i )% key == key ) then call get_value ( table , key , value ) if (. not . allocated ( value )) then call syntax_error ( error , \"Could not retrieve version string for metapackage key <\" // key // \">. Check syntax\" ) return else call request_parse ( self , value , error ) return endif end if end do ! Key is not present, metapackage not requested return end subroutine new_meta_request !> Construct a new build configuration from a TOML data structure subroutine new_meta_config ( self , table , meta_allowed , error ) !> Instance of the build configuration type ( metapackage_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys allowed to be metapackages logical , intent ( in ) :: meta_allowed (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat !> The toml table is not checked here because it already passed !> the \"new_dependencies\" check call new_meta_request ( self % openmp , \"openmp\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % stdlib , \"stdlib\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % minpack , \"minpack\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % mpi , \"mpi\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % hdf5 , \"hdf5\" , table , meta_allowed , error ) if ( allocated ( error )) return end subroutine new_meta_config !> Check local schema for allowed entries logical function is_meta_package ( key ) !> Instance of the TOML data structure character ( * ), intent ( in ) :: key select case ( key ) !> Supported metapackages case ( \"openmp\" , \"stdlib\" , \"mpi\" , \"minpack\" , \"hdf5\" ) is_meta_package = . true . case default is_meta_package = . false . end select end function is_meta_package end module fpm_manifest_metapackages","tags":"","loc":"sourcefile/meta.f90.html"},{"title":"fpm.f90 – Fortran-lang/fpm","text":"Source Code module fpm use fpm_strings , only : string_t , operator (. in .), glob , join , string_cat , & lower , str_ends_with , is_fortran_name , str_begins_with_str , & is_valid_module_name , len_trim use fpm_backend , only : build_package use fpm_command_line , only : fpm_build_settings , fpm_new_settings , & fpm_run_settings , fpm_install_settings , fpm_test_settings , & fpm_clean_settings use fpm_dependency , only : new_dependency_tree use fpm_filesystem , only : is_dir , join_path , list_files , exists , & basename , filewrite , mkdir , run , os_delete_dir use fpm_model , only : fpm_model_t , srcfile_t , show_model , fortran_features_t , & FPM_SCOPE_UNKNOWN , FPM_SCOPE_LIB , FPM_SCOPE_DEP , & FPM_SCOPE_APP , FPM_SCOPE_EXAMPLE , FPM_SCOPE_TEST use fpm_compiler , only : new_compiler , new_archiver , set_cpp_preprocessor_flags use fpm_sources , only : add_executable_sources , add_sources_from_dir use fpm_targets , only : targets_from_sources , build_target_t , build_target_ptr , & FPM_TARGET_EXECUTABLE , FPM_TARGET_ARCHIVE use fpm_manifest , only : get_package_data , package_config_t use fpm_meta , only : resolve_metapackages use fpm_error , only : error_t , fatal_error , fpm_stop use fpm_toml , only : name_is_json use , intrinsic :: iso_fortran_env , only : stdin => input_unit , & & stdout => output_unit , & & stderr => error_unit use iso_c_binding , only : c_char , c_ptr , c_int , c_null_char , c_associated , c_f_pointer use fpm_environment , only : os_is_unix use fpm_settings , only : fpm_global_settings , get_global_settings implicit none private public :: cmd_build , cmd_run , cmd_clean public :: build_model , check_modules_for_duplicates contains !> Constructs a valid fpm model from command line settings and the toml manifest. subroutine build_model ( model , settings , package , error ) type ( fpm_model_t ), intent ( out ) :: model class ( fpm_build_settings ), intent ( inout ) :: settings type ( package_config_t ), intent ( inout ) :: package type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j type ( package_config_t ) :: dependency character ( len = :), allocatable :: manifest , lib_dir logical :: has_cpp logical :: duplicates_found type ( string_t ) :: include_dir model % package_name = package % name allocate ( model % include_dirs ( 0 )) allocate ( model % link_libraries ( 0 )) allocate ( model % external_modules ( 0 )) call new_compiler ( model % compiler , settings % compiler , settings % c_compiler , & & settings % cxx_compiler , echo = settings % verbose , verbose = settings % verbose ) call new_archiver ( model % archiver , settings % archiver , & & echo = settings % verbose , verbose = settings % verbose ) if ( model % compiler % is_unknown ()) then write ( * , '(*(a:,1x))' ) & \"\" , \"Unknown compiler\" , model % compiler % fc , \"requested!\" , & \"Defaults for this compiler might be incorrect\" end if call new_compiler_flags ( model , settings ) model % build_prefix = join_path ( \"build\" , basename ( model % compiler % fc )) model % include_tests = settings % build_tests model % enforce_module_names = package % build % module_naming model % module_prefix = package % build % module_prefix ! Resolve meta-dependencies into the package and the model call resolve_metapackages ( model , package , settings , error ) if ( allocated ( error )) return ! Create dependencies call new_dependency_tree ( model % deps , cache = join_path ( \"build\" , \"cache.toml\" )) ! Build and resolve model dependencies call model % deps % add ( package , error ) if ( allocated ( error )) return ! Update dependencies where needed call model % deps % update ( error ) if ( allocated ( error )) return ! build/ directory should now exist if (. not . exists ( \"build/.gitignore\" )) then call filewrite ( join_path ( \"build\" , \".gitignore\" ),[ \"*\" ]) end if allocate ( model % packages ( model % deps % ndep )) has_cpp = . false . do i = 1 , model % deps % ndep associate ( dep => model % deps % dep ( i )) manifest = join_path ( dep % proj_dir , \"fpm.toml\" ) call get_package_data ( dependency , manifest , error , apply_defaults = . true .) if ( allocated ( error )) exit model % packages ( i )% name = dependency % name associate ( features => model % packages ( i )% features ) features % implicit_typing = dependency % fortran % implicit_typing features % implicit_external = dependency % fortran % implicit_external features % source_form = dependency % fortran % source_form end associate model % packages ( i )% version = package % version % s () !> Add this dependency's manifest macros call model % packages ( i )% preprocess % destroy () if ( allocated ( dependency % preprocess )) then do j = 1 , size ( dependency % preprocess ) call model % packages ( i )% preprocess % add_config ( dependency % preprocess ( j )) end do end if !> Add this dependency's package-level macros if ( allocated ( dep % preprocess )) then do j = 1 , size ( dep % preprocess ) call model % packages ( i )% preprocess % add_config ( dep % preprocess ( j )) end do end if if ( model % packages ( i )% preprocess % is_cpp ()) has_cpp = . true . if (. not . allocated ( model % packages ( i )% sources )) allocate ( model % packages ( i )% sources ( 0 )) if ( allocated ( dependency % library )) then if ( allocated ( dependency % library % source_dir )) then lib_dir = join_path ( dep % proj_dir , dependency % library % source_dir ) if ( is_dir ( lib_dir )) then call add_sources_from_dir ( model % packages ( i )% sources , lib_dir , FPM_SCOPE_LIB , & with_f_ext = model % packages ( i )% preprocess % suffixes , error = error ) if ( allocated ( error )) exit end if end if if ( allocated ( dependency % library % include_dir )) then do j = 1 , size ( dependency % library % include_dir ) include_dir % s = join_path ( dep % proj_dir , dependency % library % include_dir ( j )% s ) if ( is_dir ( include_dir % s )) then model % include_dirs = [ model % include_dirs , include_dir ] end if end do end if end if if ( allocated ( dependency % build % link )) then model % link_libraries = [ model % link_libraries , dependency % build % link ] end if if ( allocated ( dependency % build % external_modules )) then model % external_modules = [ model % external_modules , dependency % build % external_modules ] end if ! Copy naming conventions from this dependency's manifest model % packages ( i )% enforce_module_names = dependency % build % module_naming model % packages ( i )% module_prefix = dependency % build % module_prefix end associate end do if ( allocated ( error )) return ! Add optional flags if ( has_cpp ) call set_cpp_preprocessor_flags ( model % compiler % id , model % fortran_compile_flags ) ! Add sources from executable directories if ( is_dir ( 'app' ) . and . package % build % auto_executables ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'app' , FPM_SCOPE_APP , & with_executables = . true ., with_f_ext = model % packages ( 1 )% preprocess % suffixes ,& error = error ) if ( allocated ( error )) then return end if end if if ( is_dir ( 'example' ) . and . package % build % auto_examples ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'example' , FPM_SCOPE_EXAMPLE , & with_executables = . true ., & with_f_ext = model % packages ( 1 )% preprocess % suffixes , error = error ) if ( allocated ( error )) then return end if end if if ( is_dir ( 'test' ) . and . package % build % auto_tests ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'test' , FPM_SCOPE_TEST , & with_executables = . true ., & with_f_ext = model % packages ( 1 )% preprocess % suffixes , error = error ) if ( allocated ( error )) then return endif end if if ( allocated ( package % executable )) then call add_executable_sources ( model % packages ( 1 )% sources , package % executable , FPM_SCOPE_APP , & auto_discover = package % build % auto_executables , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return end if end if if ( allocated ( package % example )) then call add_executable_sources ( model % packages ( 1 )% sources , package % example , FPM_SCOPE_EXAMPLE , & auto_discover = package % build % auto_examples , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return end if end if if ( allocated ( package % test )) then call add_executable_sources ( model % packages ( 1 )% sources , package % test , FPM_SCOPE_TEST , & auto_discover = package % build % auto_tests , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return endif endif if ( settings % verbose ) then write ( * , * ) ' BUILD_NAME: ' , model % build_prefix write ( * , * ) ' COMPILER: ' , model % compiler % fc write ( * , * ) ' C COMPILER: ' , model % compiler % cc write ( * , * ) ' CXX COMPILER: ' , model % compiler % cxx write ( * , * ) ' COMPILER OPTIONS: ' , model % fortran_compile_flags write ( * , * ) ' C COMPILER OPTIONS: ' , model % c_compile_flags write ( * , * ) ' CXX COMPILER OPTIONS: ' , model % cxx_compile_flags write ( * , * ) ' LINKER OPTIONS: ' , model % link_flags write ( * , * ) ' INCLUDE DIRECTORIES: [' , string_cat ( model % include_dirs , ',' ), ']' end if ! Check for invalid module names call check_module_names ( model , error ) if ( allocated ( error )) return ! Check for duplicate modules duplicates_found = . false . call check_modules_for_duplicates ( model , duplicates_found ) if ( duplicates_found ) then call fpm_stop ( 1 , '*build_model*:Error: One or more duplicate module names found.' ) end if end subroutine build_model !> Initialize model compiler flags subroutine new_compiler_flags ( model , settings ) type ( fpm_model_t ), intent ( inout ) :: model type ( fpm_build_settings ), intent ( in ) :: settings character ( len = :), allocatable :: flags , cflags , cxxflags , ldflags if ( settings % flag == '' ) then flags = model % compiler % get_default_flags ( settings % profile == \"release\" ) else flags = settings % flag select case ( settings % profile ) case ( \"release\" , \"debug\" ) flags = flags // model % compiler % get_default_flags ( settings % profile == \"release\" ) end select end if cflags = trim ( settings % cflag ) cxxflags = trim ( settings % cxxflag ) ldflags = trim ( settings % ldflag ) model % fortran_compile_flags = flags model % c_compile_flags = cflags model % cxx_compile_flags = cxxflags model % link_flags = ldflags end subroutine new_compiler_flags ! Check for duplicate modules subroutine check_modules_for_duplicates ( model , duplicates_found ) type ( fpm_model_t ), intent ( in ) :: model integer :: maxsize integer :: i , j , k , l , m , modi type ( string_t ), allocatable :: modules (:) logical :: duplicates_found ! Initialise the size of array maxsize = 0 ! Get number of modules provided by each source file of every package do i = 1 , size ( model % packages ) do j = 1 , size ( model % packages ( i )% sources ) if ( allocated ( model % packages ( i )% sources ( j )% modules_provided )) then maxsize = maxsize + size ( model % packages ( i )% sources ( j )% modules_provided ) end if end do end do ! Allocate array to contain distinct names of modules allocate ( modules ( maxsize )) ! Initialise index to point at start of the newly allocated array modi = 1 ! Loop through modules provided by each source file of every package ! Add it to the array if it is not already there ! Otherwise print out warning about duplicates do k = 1 , size ( model % packages ) do l = 1 , size ( model % packages ( k )% sources ) if ( allocated ( model % packages ( k )% sources ( l )% modules_provided )) then do m = 1 , size ( model % packages ( k )% sources ( l )% modules_provided ) if ( model % packages ( k )% sources ( l )% modules_provided ( m )% s . in . modules (: modi - 1 )) then write ( stderr , * ) \"Warning: Module \" , model % packages ( k )% sources ( l )% modules_provided ( m )% s , & \" in \" , model % packages ( k )% sources ( l )% file_name , \" is a duplicate\" duplicates_found = . true . else modules ( modi ) = model % packages ( k )% sources ( l )% modules_provided ( m ) modi = modi + 1 end if end do end if end do end do end subroutine check_modules_for_duplicates ! Check names of all modules in this package and its dependencies subroutine check_module_names ( model , error ) type ( fpm_model_t ), intent ( in ) :: model type ( error_t ), allocatable , intent ( out ) :: error integer :: k , l , m logical :: valid , errors_found , enforce_this_file type ( string_t ) :: package_name , module_name , package_prefix errors_found = . false . ! Loop through modules provided by each source file of every package ! Add it to the array if it is not already there ! Otherwise print out warning about duplicates do k = 1 , size ( model % packages ) package_name = string_t ( model % packages ( k )% name ) ! Custom prefix is taken from each dependency's manifest if ( model % packages ( k )% enforce_module_names ) then package_prefix = model % packages ( k )% module_prefix else package_prefix = string_t ( \"\" ) end if ! Warn the user if some of the dependencies have loose naming if ( model % enforce_module_names . and . . not . model % packages ( k )% enforce_module_names ) then write ( stderr , * ) \"Warning: Dependency \" , package_name % s // & \" does not enforce module naming, but project does. \" end if do l = 1 , size ( model % packages ( k )% sources ) ! Module naming is not enforced in test modules enforce_this_file = model % enforce_module_names . and . & model % packages ( k )% sources ( l )% unit_scope /= FPM_SCOPE_TEST if ( allocated ( model % packages ( k )% sources ( l )% modules_provided )) then do m = 1 , size ( model % packages ( k )% sources ( l )% modules_provided ) module_name = model % packages ( k )% sources ( l )% modules_provided ( m ) valid = is_valid_module_name ( module_name , & package_name , & package_prefix , & enforce_this_file ) if (. not . valid ) then if ( enforce_this_file ) then if ( len_trim ( package_prefix ) > 0 ) then write ( stderr , * ) \"ERROR: Module \" , module_name % s , & \" in \" , model % packages ( k )% sources ( l )% file_name , & \" does not match its package name (\" // package_name % s // & \") or custom prefix (\" // package_prefix % s // \").\" else write ( stderr , * ) \"ERROR: Module \" , module_name % s , & \" in \" , model % packages ( k )% sources ( l )% file_name , & \" does not match its package name (\" // package_name % s // \").\" endif else write ( stderr , * ) \"ERROR: Module \" , module_name % s , & \" in \" , model % packages ( k )% sources ( l )% file_name , & \" has an invalid Fortran name. \" end if errors_found = . true . end if end do end if end do end do if ( errors_found ) then if ( model % enforce_module_names ) & write ( stderr , * ) \" Hint: Try disabling module naming in the manifest: [build] module-naming=false . \" call fatal_error ( error , \"The package contains invalid module names. \" // & \"Naming conventions \" // merge ( 'are' , 'not' , model % enforce_module_names ) // & \" being requested.\" ) end if end subroutine check_module_names subroutine cmd_build ( settings ) type ( fpm_build_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( error_t ), allocatable :: error integer :: i call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Package error: ' // error % message ) end if call build_model ( model , settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Model error: ' // error % message ) end if call targets_from_sources ( targets , model , settings % prune , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Target error: ' // error % message ) end if !> Dump model to file if ( len_trim ( settings % dump ) > 0 ) then call model % dump ( trim ( settings % dump ), error , json = name_is_json ( trim ( settings % dump ))) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_build* Model dump error: ' // error % message ) endif if ( settings % list ) then do i = 1 , size ( targets ) write ( stderr , * ) targets ( i )% ptr % output_file enddo else if ( settings % show_model ) then call show_model ( model ) else call build_package ( targets , model , verbose = settings % verbose ) endif end subroutine cmd_build subroutine cmd_run ( settings , test ) class ( fpm_run_settings ), intent ( inout ) :: settings logical , intent ( in ) :: test integer :: i , j , col_width logical :: found ( size ( settings % name )) type ( error_t ), allocatable :: error type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( string_t ) :: exe_cmd type ( string_t ), allocatable :: executables (:) type ( build_target_t ), pointer :: exe_target type ( srcfile_t ), pointer :: exe_source integer :: run_scope , firsterror integer , allocatable :: stat (:), target_ID (:) character ( len = :), allocatable :: line call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Package error: ' // error % message ) end if call build_model ( model , settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Model error: ' // error % message ) end if call targets_from_sources ( targets , model , settings % prune , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Targets error: ' // error % message ) end if if ( test ) then run_scope = FPM_SCOPE_TEST else run_scope = merge ( FPM_SCOPE_EXAMPLE , FPM_SCOPE_APP , settings % example ) end if ! Enumerate executable targets to run col_width = - 1 found (:) = . false . allocate ( executables ( size ( targets )), target_ID ( size ( targets ))) enumerate : do i = 1 , size ( targets ) exe_target => targets ( i )% ptr if ( should_be_run ( settings , run_scope , exe_target )) then exe_source => exe_target % dependencies ( 1 )% ptr % source col_width = max ( col_width , len ( basename ( exe_target % output_file )) + 2 ) ! Priority by name ID, or 0 if no name present (run first) j = settings % name_ID ( exe_source % exe_name ) target_ID ( i ) = j if ( j > 0 ) found ( j ) = . true . exe_cmd % s = exe_target % output_file executables ( i ) = exe_cmd else target_ID ( i ) = huge ( target_ID ( i )) endif end do enumerate ! sort executables by ascending name ID, resize call sort_executables ( target_ID , executables ) ! Check if any apps/tests were found if ( col_width < 0 ) then if ( test ) then call fpm_stop ( 0 , 'No tests to run' ) else call fpm_stop ( 0 , 'No executables to run' ) end if end if ! Check all names are valid ! or no name and found more than one file if ( any (. not . found ) ) then line = join ( settings % name ) if ( line /= '.' ) then ! do not report these special strings if ( any (. not . found )) then write ( stderr , '(A)' , advance = \"no\" ) '*cmd_run*:specified names ' do j = 1 , size ( settings % name ) if (. not . found ( j )) write ( stderr , '(A)' , advance = \"no\" ) '\"' // trim ( settings % name ( j )) // '\" ' end do write ( stderr , '(A)' ) 'not found.' write ( stderr , * ) else if ( settings % verbose ) then write ( stderr , '(A)' , advance = \"yes\" ) 'when more than one executable is available' write ( stderr , '(A)' , advance = \"yes\" ) ' program names must be specified.' endif endif call compact_list_all () if ( line == '.' . or . line == ' ' ) then ! do not report these special strings call fpm_stop ( 0 , '' ) else call fpm_stop ( 1 , '' ) endif end if call build_package ( targets , model , verbose = settings % verbose ) if ( settings % list ) then call compact_list () else allocate ( stat ( size ( executables ))) do i = 1 , size ( executables ) if ( exists ( executables ( i )% s )) then if ( settings % runner /= ' ' ) then if (. not . allocated ( settings % args )) then call run ( settings % runner_command () // ' ' // executables ( i )% s , & echo = settings % verbose , exitstat = stat ( i )) else call run ( settings % runner_command () // ' ' // executables ( i )% s // \" \" // settings % args , & echo = settings % verbose , exitstat = stat ( i )) endif else if (. not . allocated ( settings % args )) then call run ( executables ( i )% s , echo = settings % verbose , exitstat = stat ( i )) else call run ( executables ( i )% s // \" \" // settings % args , echo = settings % verbose , & exitstat = stat ( i )) endif endif else call fpm_stop ( 1 , '*cmd_run*:' // executables ( i )% s // ' not found' ) end if end do if ( any ( stat /= 0 )) then do i = 1 , size ( stat ) if ( stat ( i ) /= 0 ) then write ( stderr , '(*(g0:,1x))' ) ' Execution for object \"' , basename ( executables ( i )% s ),& '\" returned exit code ' , stat ( i ) end if end do firsterror = findloc ( stat /= 0 , value = . true ., dim = 1 ) call fpm_stop ( stat ( firsterror ), '*cmd_run*:stopping due to failed executions' ) end if end if contains subroutine compact_list_all () integer , parameter :: LINE_WIDTH = 80 integer :: ii , jj , nCol jj = 1 nCol = LINE_WIDTH / col_width write ( stderr , * ) 'Available names:' do ii = 1 , size ( targets ) exe_target => targets ( ii )% ptr if ( exe_target % target_type == FPM_TARGET_EXECUTABLE . and . & allocated ( exe_target % dependencies )) then exe_source => exe_target % dependencies ( 1 )% ptr % source if ( exe_source % unit_scope == run_scope ) then write ( stderr , '(A)' , advance = ( merge ( \"yes\" , \"no \" , modulo ( jj , nCol ) == 0 ))) & & [ character ( len = col_width ) :: basename ( exe_target % output_file , suffix = . false .)] jj = jj + 1 end if end if end do write ( stderr , * ) end subroutine compact_list_all subroutine compact_list () integer , parameter :: LINE_WIDTH = 80 integer :: ii , jj , nCol jj = 1 nCol = LINE_WIDTH / col_width write ( stderr , * ) 'Matched names:' do ii = 1 , size ( executables ) write ( stderr , '(A)' , advance = ( merge ( \"yes\" , \"no \" , modulo ( jj , nCol ) == 0 ))) & & [ character ( len = col_width ) :: basename ( executables ( ii )% s , suffix = . false .)] jj = jj + 1 end do write ( stderr , * ) end subroutine compact_list end subroutine cmd_run subroutine delete_skip ( is_unix ) !> delete directories in the build folder, skipping dependencies logical , intent ( in ) :: is_unix character ( len = :), allocatable :: dir type ( string_t ), allocatable :: files (:) integer :: i call list_files ( 'build' , files , . false .) do i = 1 , size ( files ) if ( is_dir ( files ( i )% s )) then dir = files ( i )% s if (. not . str_ends_with ( dir , 'dependencies' )) call os_delete_dir ( is_unix , dir ) end if end do end subroutine delete_skip !> Delete the build directory including or excluding dependencies. Can be used !> to clear the registry cache. subroutine cmd_clean ( settings ) !> Settings for the clean command. class ( fpm_clean_settings ), intent ( in ) :: settings character :: user_response type ( fpm_global_settings ) :: global_settings type ( error_t ), allocatable :: error ! Clear registry cache if ( settings % registry_cache ) then call get_global_settings ( global_settings , error ) if ( allocated ( error )) return call os_delete_dir ( os_is_unix (), global_settings % registry_settings % cache_path ) end if if ( is_dir ( 'build' )) then ! Remove the entire build directory if ( settings % clean_all ) then call os_delete_dir ( os_is_unix (), 'build' ); return ! Remove the build directory but skip dependencies else if ( settings % clean_skip ) then call delete_skip ( os_is_unix ()); return end if ! Prompt to remove the build directory but skip dependencies write ( stdout , '(A)' , advance = 'no' ) \"Delete build, excluding dependencies (y/n)? \" read ( stdin , '(A1)' ) user_response if ( lower ( user_response ) == 'y' ) call delete_skip ( os_is_unix ()) else write ( stdout , '(A)' ) \"fpm: No build directory found.\" end if end subroutine cmd_clean !> Sort executables by namelist ID, and trim unused values pure subroutine sort_executables ( target_ID , executables ) integer , allocatable , intent ( inout ) :: target_ID (:) type ( string_t ), allocatable , intent ( inout ) :: executables (:) integer :: i , j , n , used n = size ( target_ID ) used = 0 sort : do i = 1 , n do j = i + 1 , n if ( target_ID ( j ) < target_ID ( i )) & call swap ( target_ID ( i ), target_ID ( j ), executables ( i ), executables ( j )) end do if ( target_ID ( i ) < huge ( target_ID ( i ))) used = i end do sort if ( used > 0 . and . used < n ) then target_ID = target_ID ( 1 : used ) executables = executables ( 1 : used ) end if contains elemental subroutine swap ( t1 , t2 , e1 , e2 ) integer , intent ( inout ) :: t1 , t2 type ( string_t ), intent ( inout ) :: e1 , e2 integer :: tmp type ( string_t ) :: etmp tmp = t1 t1 = t2 t2 = tmp etmp = e1 e1 = e2 e2 = etmp end subroutine swap end subroutine sort_executables !> Check if an executable should be run logical function should_be_run ( settings , run_scope , exe_target ) class ( fpm_run_settings ), intent ( in ) :: settings integer , intent ( in ) :: run_scope type ( build_target_t ), intent ( in ) :: exe_target integer :: j if ( exe_target % is_executable_target ( run_scope )) then associate ( exe_source => exe_target % dependencies ( 1 )% ptr % source ) if ( exe_source % unit_scope /= run_scope ) then ! Other scope should_be_run = . false . elseif ( size ( settings % name ) == 0 . or . settings % list ) then ! Run all or list all should_be_run = . true . else ! Is found in list should_be_run = settings % name_ID ( exe_source % exe_name ) > 0 end if end associate else !> Invalid target should_be_run = . false . endif end function should_be_run end module fpm","tags":"","loc":"sourcefile/fpm.f90.html"},{"title":"export.f90 – Fortran-lang/fpm","text":"Source Code module fpm_cmd_export use fpm_command_line , only : fpm_export_settings use fpm_dependency , only : dependency_tree_t , new_dependency_tree use fpm_error , only : error_t , fpm_stop use fpm_filesystem , only : join_path use fpm_manifest , only : package_config_t , get_package_data use fpm_toml , only : name_is_json use fpm_model , only : fpm_model_t use fpm , only : build_model implicit none private public :: cmd_export contains !> Entry point for the export subcommand subroutine cmd_export ( settings ) !> Representation of the command line arguments type ( fpm_export_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( dependency_tree_t ) :: deps type ( fpm_model_t ) :: model type ( error_t ), allocatable :: error integer :: ii character ( len = :), allocatable :: filename if ( len_trim ( settings % dump_manifest ) <= 0 . and . & len_trim ( settings % dump_model ) <= 0 . and . & len_trim ( settings % dump_dependencies ) <= 0 ) then call fpm_stop ( 0 , '*cmd_export* exiting: no manifest/model/dependencies keyword provided' ) end if !> Read in manifest call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) !> Export manifest if ( len_trim ( settings % dump_manifest ) > 0 ) then filename = trim ( settings % dump_manifest ) call package % dump ( filename , error , json = name_is_json ( filename )) end if !> Export dependency tree if ( len_trim ( settings % dump_dependencies ) > 0 ) then !> Generate dependency tree filename = join_path ( \"build\" , \"cache.toml\" ) call new_dependency_tree ( deps , cache = filename , verbosity = merge ( 2 , 1 , settings % verbose )) call deps % add ( package , error ) call handle_error ( error ) !> Export dependency tree filename = settings % dump_dependencies call deps % dump ( filename , error , json = name_is_json ( filename )) call handle_error ( error ) end if !> Export full model if ( len_trim ( settings % dump_model ) > 0 ) then call build_model ( model , settings % fpm_build_settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_export* Model error: ' // error % message ) end if filename = settings % dump_model call model % dump ( filename , error , json = name_is_json ( filename )) call handle_error ( error ) end if end subroutine cmd_export !> Error handling for this command subroutine handle_error ( error ) !> Potential error type ( error_t ), intent ( in ), optional :: error if ( present ( error )) then call fpm_stop ( 1 , '*cmd_export* error: ' // error % message ) end if end subroutine handle_error end module fpm_cmd_export","tags":"","loc":"sourcefile/export.f90.html"},{"title":"package.f90 – Fortran-lang/fpm","text":"Source Code !> Define the package data containing the meta data from the configuration file. !> !> The package data defines a Fortran type corresponding to the respective !> TOML document, after creating it from a package file no more interaction !> with the TOML document is required. !> !> Every configuration type provides it custom constructor (prefixed with `new_`) !> and knows how to deserialize itself from a TOML document. !> To ensure we find no untracked content in the package file all keywords are !> checked and possible entries have to be explicitly allowed in the `check` !> function. !> If entries are mutally exclusive or interdependent inside the current table !> the `check` function is required to enforce this schema on the data structure. !> !> The package file root allows the following keywords !> !>```toml !>name = \"string\" !>version = \"string\" !>license = \"string\" !>author = \"string\" !>maintainer = \"string\" !>copyright = \"string\" !>[library] !>[dependencies] !>[dev-dependencies] !>[profiles] !>[build] !>[install] !>[fortran] !>[[ executable ]] !>[[ example ]] !>[[ test ]] !>[extra] !>``` module fpm_manifest_package use fpm_manifest_build , only : build_config_t , new_build_config use fpm_manifest_dependency , only : dependency_config_t , new_dependencies use fpm_manifest_profile , only : profile_config_t , new_profiles , get_default_profiles use fpm_manifest_example , only : example_config_t , new_example use fpm_manifest_executable , only : executable_config_t , new_executable use fpm_manifest_fortran , only : fortran_config_t , new_fortran_config use fpm_manifest_library , only : library_config_t , new_library use fpm_manifest_install , only : install_config_t , new_install_config use fpm_manifest_test , only : test_config_t , new_test use fpm_manifest_preprocess , only : preprocess_config_t , new_preprocessors use fpm_manifest_metapackages , only : metapackage_config_t , new_meta_config use fpm_filesystem , only : exists , getline , join_path use fpm_error , only : error_t , fatal_error , syntax_error , bad_name_error use fpm_toml , only : toml_table , toml_array , toml_key , toml_stat , get_value , len , & serializable_t , set_value , set_string , set_list , add_table use fpm_versioning , only : version_t , new_version implicit none private public :: package_config_t , new_package interface unique_programs module procedure :: unique_programs1 module procedure :: unique_programs2 end interface unique_programs !> Package meta data type , extends ( serializable_t ) :: package_config_t !> Name of the package character ( len = :), allocatable :: name !> Package version type ( version_t ) :: version !> Build configuration data type ( build_config_t ) :: build !> Metapackage data type ( metapackage_config_t ) :: meta !> Installation configuration data type ( install_config_t ) :: install !> Fortran meta data type ( fortran_config_t ) :: fortran !> License meta data character ( len = :), allocatable :: license !> Author meta data character ( len = :), allocatable :: author !> Maintainer meta data character ( len = :), allocatable :: maintainer !> Copyright meta data character ( len = :), allocatable :: copyright !> Library meta data type ( library_config_t ), allocatable :: library !> Executable meta data type ( executable_config_t ), allocatable :: executable (:) !> Dependency meta data type ( dependency_config_t ), allocatable :: dependency (:) !> Development dependency meta data type ( dependency_config_t ), allocatable :: dev_dependency (:) !> Profiles meta data type ( profile_config_t ), allocatable :: profiles (:) !> Example meta data type ( example_config_t ), allocatable :: example (:) !> Test meta data type ( test_config_t ), allocatable :: test (:) !> Preprocess meta data type ( preprocess_config_t ), allocatable :: preprocess (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => manifest_is_same procedure :: dump_to_toml procedure :: load_from_toml end type package_config_t character ( len =* ), parameter , private :: class_name = 'package_config_t' contains !> Construct a new package configuration from a TOML data structure subroutine new_package ( self , table , root , error ) !> Instance of the package configuration type ( package_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( len =* ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error ! Backspace (8), tabulator (9), newline (10), formfeed (12) and carriage ! return (13) are invalid in package names character ( len =* ), parameter :: invalid_chars = & achar ( 8 ) // achar ( 9 ) // achar ( 10 ) // achar ( 12 ) // achar ( 13 ) type ( toml_table ), pointer :: child , node type ( toml_array ), pointer :: children character ( len = :), allocatable :: version , version_file integer :: ii , nn , stat , io call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve package name\" ) return end if if ( bad_name_error ( error , 'package' , self % name )) then return endif call get_value ( table , \"license\" , self % license ) call get_value ( table , \"author\" , self % author ) call get_value ( table , \"maintainer\" , self % maintainer ) call get_value ( table , \"copyright\" , self % copyright ) if ( len ( self % name ) <= 0 ) then call syntax_error ( error , \"Package name must be a non-empty string\" ) return end if ii = scan ( self % name , invalid_chars ) if ( ii > 0 ) then call syntax_error ( error , \"Package name contains invalid characters\" ) return end if call get_value ( table , \"build\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for build entry, must be a table\" ) return end if call new_build_config ( self % build , child , self % name , error ) if ( allocated ( error )) return call get_value ( table , \"install\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for install entry, must be a table\" ) return end if call new_install_config ( self % install , child , error ) if ( allocated ( error )) return call get_value ( table , \"fortran\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for fortran entry, must be a table\" ) return end if call new_fortran_config ( self % fortran , child , error ) if ( allocated ( error )) return call get_value ( table , \"version\" , version , \"0\" ) call new_version ( self % version , version , error ) if ( allocated ( error ) . and . present ( root )) then version_file = join_path ( root , version ) if ( exists ( version_file )) then deallocate ( error ) open ( file = version_file , newunit = io , iostat = stat ) if ( stat == 0 ) then call getline ( io , version , iostat = stat ) end if if ( stat == 0 ) then close ( io , iostat = stat ) end if if ( stat == 0 ) then call new_version ( self % version , version , error ) else call fatal_error ( error , \"Reading version number from file '\" & & // version_file // \"' failed\" ) end if end if end if if ( allocated ( error )) return call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , root , self % meta , error ) if ( allocated ( error )) return end if call get_value ( table , \"dev-dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dev_dependency , child , root , error = error ) if ( allocated ( error )) return end if call get_value ( table , \"library\" , child , requested = . false .) if ( associated ( child )) then allocate ( self % library ) call new_library ( self % library , child , error ) if ( allocated ( error )) return end if call get_value ( table , \"profiles\" , child , requested = . false .) if ( associated ( child )) then call new_profiles ( self % profiles , child , error ) if ( allocated ( error )) return else self % profiles = get_default_profiles ( error ) if ( allocated ( error )) return end if call get_value ( table , \"executable\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % executable ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve executable from array entry\" ) exit end if call new_executable ( self % executable ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % executable , error ) if ( allocated ( error )) return end if call get_value ( table , \"example\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % example ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve example from array entry\" ) exit end if call new_example ( self % example ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % example , error ) if ( allocated ( error )) return if ( allocated ( self % executable )) then call unique_programs ( self % executable , self % example , error ) if ( allocated ( error )) return end if end if call get_value ( table , \"test\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % test ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve test from array entry\" ) exit end if call new_test ( self % test ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % test , error ) if ( allocated ( error )) return end if call get_value ( table , \"preprocess\" , child , requested = . false .) if ( associated ( child )) then call new_preprocessors ( self % preprocess , child , error ) if ( allocated ( error )) return end if end subroutine new_package !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) logical :: name_present integer :: ikey name_present = . false . call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Package file is empty\" ) return end if do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in package file\" ) exit case ( \"name\" ) name_present = . true . case ( \"version\" , \"license\" , \"author\" , \"maintainer\" , \"copyright\" , & & \"description\" , \"keywords\" , \"categories\" , \"homepage\" , \"build\" , & & \"dependencies\" , \"dev-dependencies\" , \"profiles\" , \"test\" , \"executable\" , & & \"example\" , \"library\" , \"install\" , \"extra\" , \"preprocess\" , \"fortran\" ) continue end select end do if ( allocated ( error )) return if (. not . name_present ) then call syntax_error ( error , \"Package name is not provided, please add a name entry\" ) end if end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the package configuration class ( package_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ii character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' , & & fmti = '(\"#\", 1x, a, t30, i0)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Package\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if call self % build % info ( unit , pr - 1 ) call self % install % info ( unit , pr - 1 ) if ( allocated ( self % library )) then write ( unit , fmt ) \"- target\" , \"archive\" call self % library % info ( unit , pr - 1 ) end if if ( allocated ( self % executable )) then if ( size ( self % executable ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- executables\" , size ( self % executable ) end if do ii = 1 , size ( self % executable ) call self % executable ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % dependency )) then if ( size ( self % dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- dependencies\" , size ( self % dependency ) end if do ii = 1 , size ( self % dependency ) call self % dependency ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % example )) then if ( size ( self % example ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- examples\" , size ( self % example ) end if do ii = 1 , size ( self % example ) call self % example ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % test )) then if ( size ( self % test ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- tests\" , size ( self % test ) end if do ii = 1 , size ( self % test ) call self % test ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % dev_dependency )) then if ( size ( self % dev_dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- development deps.\" , size ( self % dev_dependency ) end if do ii = 1 , size ( self % dev_dependency ) call self % dev_dependency ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % profiles )) then if ( size ( self % profiles ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- profiles\" , size ( self % profiles ) end if do ii = 1 , size ( self % profiles ) call self % profiles ( ii )% info ( unit , pr - 1 ) end do end if end subroutine info !> Check whether or not the names in a set of executables are unique subroutine unique_programs1 ( executable , error ) !> Array of executables class ( executable_config_t ), intent ( in ) :: executable (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j do i = 1 , size ( executable ) do j = 1 , i - 1 if ( executable ( i )% name == executable ( j )% name ) then call fatal_error ( error , \"The program named '\" // & executable ( j )% name // \"' is duplicated. \" // & \"Unique program names are required.\" ) exit end if end do end do if ( allocated ( error )) return end subroutine unique_programs1 !> Check whether or not the names in a set of executables are unique subroutine unique_programs2 ( executable_i , executable_j , error ) !> Array of executables class ( executable_config_t ), intent ( in ) :: executable_i (:) !> Array of executables class ( executable_config_t ), intent ( in ) :: executable_j (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j do i = 1 , size ( executable_i ) do j = 1 , size ( executable_j ) if ( executable_i ( i )% name == executable_j ( j )% name ) then call fatal_error ( error , \"The program named '\" // & executable_j ( j )% name // \"' is duplicated. \" // & \"Unique program names are required.\" ) exit end if end do end do if ( allocated ( error )) return end subroutine unique_programs2 logical function manifest_is_same ( this , that ) class ( package_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii manifest_is_same = . false . select type ( other => that ) type is ( package_config_t ) if (. not . this % name == other % name ) return if (. not . this % version == other % version ) return if (. not . this % build == other % build ) return if (. not . this % install == other % install ) return if (. not . this % fortran == other % fortran ) return if (. not . this % license == other % license ) return if (. not . this % author == other % author ) return if (. not . this % maintainer == other % maintainer ) return if (. not . this % copyright == other % copyright ) return if ( allocated ( this % library ). neqv . allocated ( other % library )) return if ( allocated ( this % library )) then if (. not . this % library == other % library ) return endif if ( allocated ( this % executable ). neqv . allocated ( other % executable )) return if ( allocated ( this % executable )) then if (. not . size ( this % executable ) == size ( other % executable )) return do ii = 1 , size ( this % executable ) if (. not . this % executable ( ii ) == other % executable ( ii )) return end do end if if ( allocated ( this % dependency ). neqv . allocated ( other % dependency )) return if ( allocated ( this % dependency )) then if (. not . size ( this % dependency ) == size ( other % dependency )) return do ii = 1 , size ( this % dependency ) if (. not . this % dependency ( ii ) == other % dependency ( ii )) return end do end if if ( allocated ( this % dev_dependency ). neqv . allocated ( other % dev_dependency )) return if ( allocated ( this % dev_dependency )) then if (. not . size ( this % dev_dependency ) == size ( other % dev_dependency )) return do ii = 1 , size ( this % dev_dependency ) if (. not . this % dev_dependency ( ii ) == other % dev_dependency ( ii )) return end do end if if ( allocated ( this % profiles ). neqv . allocated ( other % profiles )) return if ( allocated ( this % profiles )) then if (. not . size ( this % profiles ) == size ( other % profiles )) return do ii = 1 , size ( this % profiles ) if (. not . this % profiles ( ii ) == other % profiles ( ii )) return end do end if if ( allocated ( this % example ). neqv . allocated ( other % example )) return if ( allocated ( this % example )) then if (. not . size ( this % example ) == size ( other % example )) return do ii = 1 , size ( this % example ) if (. not . this % example ( ii ) == other % example ( ii )) return end do end if if ( allocated ( this % preprocess ). neqv . allocated ( other % preprocess )) return if ( allocated ( this % preprocess )) then if (. not . size ( this % preprocess ) == size ( other % preprocess )) return do ii = 1 , size ( this % preprocess ) if (. not . this % preprocess ( ii ) == other % preprocess ( ii )) return end do end if if ( allocated ( this % test ). neqv . allocated ( other % test )) return if ( allocated ( this % test )) then if (. not . size ( this % test ) == size ( other % test )) return do ii = 1 , size ( this % test ) if (. not . this % test ( ii ) == other % test ( ii )) return end do end if class default ! Not the same type return end select !> All checks passed! manifest_is_same = . true . end function manifest_is_same !> Dump manifest to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( package_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii type ( toml_table ), pointer :: ptr , ptr_pkg character ( 30 ) :: unnamed character ( 128 ) :: profile_name call set_string ( table , \"name\" , self % name , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"version\" , self % version % s (), error , class_name ) if ( allocated ( error )) return call set_string ( table , \"license\" , self % license , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"author\" , self % author , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"maintainer\" , self % maintainer , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"copyright\" , self % copyright , error , class_name ) if ( allocated ( error )) return call add_table ( table , \"build\" , ptr , error , class_name ) if ( allocated ( error )) return call self % build % dump_to_toml ( ptr , error ) if ( allocated ( error )) return call add_table ( table , \"fortran\" , ptr , error , class_name ) if ( allocated ( error )) return call self % fortran % dump_to_toml ( ptr , error ) if ( allocated ( error )) return call add_table ( table , \"install\" , ptr , error , class_name ) if ( allocated ( error )) return call self % install % dump_to_toml ( ptr , error ) if ( allocated ( error )) return if ( allocated ( self % library )) then call add_table ( table , \"library\" , ptr , error , class_name ) if ( allocated ( error )) return call self % library % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end if if ( allocated ( self % executable )) then call add_table ( table , \"executable\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'executable' table \" ) return end if do ii = 1 , size ( self % executable ) associate ( pkg => self % executable ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'EXECUTABLE' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(executable)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(executable)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % dependency )) then call add_table ( table , \"dependencies\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'dependencies' table \" ) return end if do ii = 1 , size ( self % dependency ) associate ( pkg => self % dependency ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'DEPENDENCY' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(dependencies)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(dependencies)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % dev_dependency )) then call add_table ( table , \"dev-dependencies\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'dev-dependencies' table \" ) return end if do ii = 1 , size ( self % dev_dependency ) associate ( pkg => self % dev_dependency ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'DEV-DEPENDENCY' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(dev-dependencies)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(dev-dependencies)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % profiles )) then call add_table ( table , \"profiles\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'profiles' table \" ) return end if do ii = 1 , size ( self % profiles ) associate ( pkg => self % profiles ( ii )) !> Duplicate profile names are possible, as multiple profiles are possible with the !> same name, same compiler, etc. So, use a unique name here write ( profile_name , 2 ) ii call add_table ( ptr_pkg , trim ( profile_name ), ptr , error , class_name // '(profiles)' ) if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % example )) then call add_table ( table , \"example\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'example' table \" ) return end if do ii = 1 , size ( self % example ) associate ( pkg => self % example ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'EXAMPLE' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(example)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(example)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % test )) then call add_table ( table , \"test\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'test' table \" ) return end if do ii = 1 , size ( self % test ) associate ( pkg => self % test ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'TEST' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(test)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(test)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % preprocess )) then call add_table ( table , \"preprocess\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'preprocess' table \" ) return end if do ii = 1 , size ( self % preprocess ) associate ( pkg => self % preprocess ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'PREPROCESS' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(preprocess)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(preprocess)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if 1 format ( 'UNNAMED_' , a , '_' , i0 ) 2 format ( 'PROFILE_' , i0 ) end subroutine dump_to_toml !> Read manifest from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( package_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: keys (:), pkg_keys (:) integer :: ierr , ii , jj character ( len = :), allocatable :: flag type ( toml_table ), pointer :: ptr , ptr_pkg call table % get_keys ( keys ) call get_value ( table , \"name\" , self % name ) call get_value ( table , \"license\" , self % license ) call get_value ( table , \"author\" , self % author ) call get_value ( table , \"maintainer\" , self % maintainer ) call get_value ( table , \"copyright\" , self % copyright ) call get_value ( table , \"version\" , flag ) call new_version ( self % version , flag , error ) if ( allocated ( error )) then error % message = class_name // ': version error from TOML table - ' // error % message return endif if ( allocated ( self % library )) deallocate ( self % library ) if ( allocated ( self % executable )) deallocate ( self % executable ) if ( allocated ( self % dependency )) deallocate ( self % dependency ) if ( allocated ( self % dev_dependency )) deallocate ( self % dev_dependency ) if ( allocated ( self % profiles )) deallocate ( self % profiles ) if ( allocated ( self % example )) deallocate ( self % example ) if ( allocated ( self % test )) deallocate ( self % test ) if ( allocated ( self % preprocess )) deallocate ( self % preprocess ) sub_deps : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"build\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving ' // keys ( ii )% key // ' table' ) return end if call self % build % load_from_toml ( ptr , error ) if ( allocated ( error )) return case ( \"install\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving ' // keys ( ii )% key // ' table' ) return end if call self % install % load_from_toml ( ptr , error ) case ( \"fortran\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving ' // keys ( ii )% key // ' table' ) return end if call self % fortran % load_from_toml ( ptr , error ) case ( \"library\" ) allocate ( self % library ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving ' // keys ( ii )% key // ' table' ) return end if call self % library % load_from_toml ( ptr , error ) case ( \"executable\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving executable table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % executable ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % executable ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"dependencies\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving dependency table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % dependency ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % dependency ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"dev-dependencies\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving dev-dependencies table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % dev_dependency ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % dev_dependency ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"profiles\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving profiles table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % profiles ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % profiles ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"example\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving example table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % example ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % example ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"test\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving test table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % test ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % test ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"preprocess\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving preprocess table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % preprocess ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % preprocess ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case default cycle sub_deps end select end do sub_deps end subroutine load_from_toml end module fpm_manifest_package","tags":"","loc":"sourcefile/package.f90.html"},{"title":"fpm_backend_output.f90 – Fortran-lang/fpm","text":"Source Code !># Build Backend Progress Output !> This module provides a derived type `build_progress_t` for printing build status !> and progress messages to the console while the backend is building the package. !> !> The `build_progress_t` type supports two modes: `normal` and `plain` !> where the former does 'pretty' output and the latter does not. !> The `normal` mode is intended for typical interactive usage whereas !> 'plain' mode is used with the `--verbose` flag or when `stdout` is not attached !> to a terminal (e.g. when piping or redirecting `stdout`). In these cases, !> the pretty output must be suppressed to avoid control codes being output. module fpm_backend_output use iso_fortran_env , only : stdout => output_unit use fpm_filesystem , only : basename use fpm_targets , only : build_target_ptr use fpm_backend_console , only : console_t , LINE_RESET , COLOR_RED , COLOR_GREEN , COLOR_YELLOW , COLOR_RESET implicit none private public build_progress_t !> Build progress object type build_progress_t !> Console object for updating console lines type ( console_t ) :: console !> Number of completed targets integer :: n_complete !> Total number of targets scheduled integer :: n_target !> 'Plain' output (no colors or updating) logical :: plain_mode = . true . !> Store needed when updating previous console lines integer , allocatable :: output_lines (:) !> Queue of scheduled build targets type ( build_target_ptr ), pointer :: target_queue (:) contains !> Output 'compiling' status for build target procedure :: compiling_status => output_status_compiling !> Output 'complete' status for build target procedure :: completed_status => output_status_complete !> Output finished status for whole package procedure :: success => output_progress_success end type build_progress_t !> Constructor for build_progress_t interface build_progress_t procedure :: new_build_progress end interface build_progress_t contains !> Initialise a new build progress object function new_build_progress ( target_queue , plain_mode ) result ( progress ) !> The queue of scheduled targets type ( build_target_ptr ), intent ( in ), target :: target_queue (:) !> Enable 'plain' output for progress object logical , intent ( in ), optional :: plain_mode !> Progress object to initialise type ( build_progress_t ) :: progress progress % n_target = size ( target_queue , 1 ) progress % target_queue => target_queue progress % plain_mode = plain_mode progress % n_complete = 0 allocate ( progress % output_lines ( progress % n_target )) end function new_build_progress !> Output 'compiling' status for build target and overall percentage progress subroutine output_status_compiling ( progress , queue_index ) !> Progress object class ( build_progress_t ), intent ( inout ) :: progress !> Index of build target in the target queue integer , intent ( in ) :: queue_index character (:), allocatable :: target_name character ( 100 ) :: output_string character ( 7 ) :: overall_progress associate ( target => progress % target_queue ( queue_index )% ptr ) if ( allocated ( target % source )) then target_name = basename ( target % source % file_name ) else target_name = basename ( target % output_file ) end if write ( overall_progress , '(A,I3,A)' ) '[' , 100 * progress % n_complete / progress % n_target , '%] ' if ( progress % plain_mode ) then ! Plain output !$omp critical write ( * , '(A7,A30)' ) overall_progress , target_name !$omp end critical else ! Pretty output write ( output_string , '(A,T40,A,A)' ) target_name , COLOR_YELLOW // 'compiling...' // COLOR_RESET call progress % console % write_line ( trim ( output_string ), progress % output_lines ( queue_index )) call progress % console % write_line ( overall_progress // 'Compiling...' , advance = . false .) end if end associate end subroutine output_status_compiling !> Output 'complete' status for build target and update overall percentage progress subroutine output_status_complete ( progress , queue_index , build_stat ) !> Progress object class ( build_progress_t ), intent ( inout ) :: progress !> Index of build target in the target queue integer , intent ( in ) :: queue_index !> Build status flag integer , intent ( in ) :: build_stat character (:), allocatable :: target_name character ( 100 ) :: output_string character ( 7 ) :: overall_progress !$omp critical progress % n_complete = progress % n_complete + 1 !$omp end critical associate ( target => progress % target_queue ( queue_index )% ptr ) if ( allocated ( target % source )) then target_name = basename ( target % source % file_name ) else target_name = basename ( target % output_file ) end if if ( build_stat == 0 ) then write ( output_string , '(A,T40,A,A)' ) target_name , COLOR_GREEN // 'done.' // COLOR_RESET else write ( output_string , '(A,T40,A,A)' ) target_name , COLOR_RED // 'failed.' // COLOR_RESET end if write ( overall_progress , '(A,I3,A)' ) '[' , 100 * progress % n_complete / progress % n_target , '%] ' if ( progress % plain_mode ) then ! Plain output !$omp critical write ( * , '(A7,A30,A7)' ) overall_progress , target_name , 'done.' !$omp end critical else ! Pretty output call progress % console % update_line ( progress % output_lines ( queue_index ), trim ( output_string )) call progress % console % write_line ( overall_progress // 'Compiling...' , advance = . false .) end if end associate end subroutine output_status_complete !> Output finished status for whole package subroutine output_progress_success ( progress ) class ( build_progress_t ), intent ( inout ) :: progress if ( progress % plain_mode ) then ! Plain output write ( * , '(A)' ) '[100%] Project compiled successfully.' else ! Pretty output write ( * , '(A)' ) LINE_RESET // COLOR_GREEN // '[100%] Project compiled successfully.' // COLOR_RESET end if end subroutine output_progress_success end module fpm_backend_output","tags":"","loc":"sourcefile/fpm_backend_output.f90.html"},{"title":"build.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the build configuration data. !> !> A build table can currently have the following fields !> !>```toml !>[build] !>auto-executables = bool !>auto-examples = bool !>auto-tests = bool !>link = [\"lib\"] !>``` module fpm_manifest_build use fpm_error , only : error_t , syntax_error , fatal_error use fpm_strings , only : string_t , len_trim , is_valid_module_prefix , operator ( == ) use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list , serializable_t , & set_value , set_string , set_list implicit none private public :: build_config_t , new_build_config !> Configuration data for build type , extends ( serializable_t ) :: build_config_t !> Automatic discovery of executables logical :: auto_executables = . true . !> Automatic discovery of examples logical :: auto_examples = . true . !> Automatic discovery of tests logical :: auto_tests = . true . !> Enforcing of package module names logical :: module_naming = . false . type ( string_t ) :: module_prefix !> Libraries to link against type ( string_t ), allocatable :: link (:) !> External modules to use type ( string_t ), allocatable :: external_modules (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => build_conf_is_same procedure :: dump_to_toml procedure :: load_from_toml end type build_config_t character ( * ), parameter , private :: class_name = 'build_config_t' contains !> Construct a new build configuration from a TOML data structure subroutine new_build_config ( self , table , package_name , error ) !> Instance of the build configuration type ( build_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Package name character ( len =* ), intent ( in ) :: package_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat call check ( table , package_name , error ) if ( allocated ( error )) return call get_value ( table , \"auto-executables\" , self % auto_executables , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-executables' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"auto-tests\" , self % auto_tests , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-tests' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"auto-examples\" , self % auto_examples , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-examples' in fpm.toml, expecting logical\" ) return end if !> Module naming: fist, attempt boolean value first call get_value ( table , \"module-naming\" , self % module_naming , . false ., stat = stat ) if ( stat == toml_stat % success ) then ! Boolean value found. Set no custom prefix. This also falls back to key not provided if ( allocated ( self % module_prefix % s )) deallocate ( self % module_prefix % s ) else !> Value found, but not a boolean. Attempt to read a prefix string call get_value ( table , \"module-naming\" , self % module_prefix % s ) if (. not . allocated ( self % module_prefix % s )) then call syntax_error ( error , \"Could not read value for 'module-naming' in fpm.toml, expecting logical or a string\" ) return end if if (. not . is_valid_module_prefix ( self % module_prefix )) then call syntax_error ( error , \"Invalid custom module name prefix for in fpm.toml: <\" // self % module_prefix % s // & \">, expecting a valid alphanumeric string\" ) return end if ! Set module naming to ON self % module_naming = . true . end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return call get_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return end subroutine new_build_config !> Check local schema for allowed entries subroutine check ( table , package_name , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Package name character ( len =* ), intent ( in ) :: package_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_keys ( list ) ! table can be empty if ( size ( list ) < 1 ) return do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case ( \"auto-executables\" , \"auto-examples\" , \"auto-tests\" , \"link\" , \"external-modules\" , \"module-naming\" ) continue case default call syntax_error ( error , 'Manifest file syntax error: key \"' // list ( ikey )% key // '\" found in the [build] ' // & 'section of package/dependency \"' // package_name // '\" fpm.toml is not allowed' ) exit end select end do end subroutine check !> Write information on build configuration instance subroutine info ( self , unit , verbosity ) !> Instance of the build configuration class ( build_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ilink , imod character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Build configuration\" write ( unit , fmt ) \" - auto-discovery (apps) \" , merge ( \"enabled \" , \"disabled\" , self % auto_executables ) write ( unit , fmt ) \" - auto-discovery (examples) \" , merge ( \"enabled \" , \"disabled\" , self % auto_examples ) write ( unit , fmt ) \" - auto-discovery (tests) \" , merge ( \"enabled \" , \"disabled\" , self % auto_tests ) write ( unit , fmt ) \" - enforce module naming \" , merge ( \"enabled \" , \"disabled\" , self % module_naming ) if ( allocated ( self % link )) then write ( unit , fmt ) \" - link against\" do ilink = 1 , size ( self % link ) write ( unit , fmt ) \" - \" // self % link ( ilink )% s end do end if if ( allocated ( self % external_modules )) then write ( unit , fmt ) \" - external modules\" do imod = 1 , size ( self % external_modules ) write ( unit , fmt ) \" - \" // self % external_modules ( imod )% s end do end if end subroutine info !> Check that two dependency trees are equal logical function build_conf_is_same ( this , that ) class ( build_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that build_conf_is_same = . false . select type ( other => that ) type is ( build_config_t ) if ( this % auto_executables . neqv . other % auto_executables ) return if ( this % auto_examples . neqv . other % auto_examples ) return if ( this % auto_tests . neqv . other % auto_tests ) return if ( this % module_naming . neqv . other % module_naming ) return if (. not . this % module_prefix == other % module_prefix ) return if (. not . this % link == other % link ) return if (. not . this % external_modules == other % external_modules ) return class default ! Not the same type return end select !> All checks passed! build_conf_is_same = . true . end function build_conf_is_same !> Dump build config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( build_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_value ( table , \"auto-executables\" , self % auto_executables , error , class_name ) if ( allocated ( error )) return call set_value ( table , \"auto-tests\" , self % auto_tests , error , class_name ) if ( allocated ( error )) return call set_value ( table , \"auto-examples\" , self % auto_examples , error , class_name ) if ( allocated ( error )) return ! Module naming can either contain a boolean value, or the prefix has_prefix : if ( self % module_naming . and . len_trim ( self % module_prefix ) > 0 ) then call set_string ( table , \"module-naming\" , self % module_prefix , error , class_name ) else call set_value ( table , \"module-naming\" , self % module_naming , error , class_name ) end if has_prefix if ( allocated ( error )) return call set_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return call set_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read build config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( build_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat call get_value ( table , \"auto-executables\" , self % auto_executables , error , class_name ) if ( allocated ( error )) return call get_value ( table , \"auto-tests\" , self % auto_tests , error , class_name ) if ( allocated ( error )) return call get_value ( table , \"auto-examples\" , self % auto_examples , error , class_name ) if ( allocated ( error )) return !> Module naming: fist, attempt boolean value first call get_value ( table , \"module-naming\" , self % module_naming , . false ., stat = stat ) if ( stat == toml_stat % success ) then ! Boolean value found. Set no custom prefix. This also falls back to key not provided if ( allocated ( self % module_prefix % s )) deallocate ( self % module_prefix % s ) else !> Value found, but not a boolean. Attempt to read a prefix string call get_value ( table , \"module-naming\" , self % module_prefix % s ) if (. not . allocated ( self % module_prefix % s )) then call syntax_error ( error , \"Could not read value for 'module-naming' in fpm.toml, expecting logical or a string\" ) return end if self % module_naming = . true . end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return call get_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return end subroutine load_from_toml end module fpm_manifest_build","tags":"","loc":"sourcefile/build.f90.html"},{"title":"test.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for a test. !> !> The test data structure is effectively a decorated version of an executable !> and shares most of its properties, except for the defaults and can be !> handled under most circumstances just like any other executable. !> !> A test table can currently have the following fields !> !>```toml !>[[ test ]] !>name = \"string\" !>source-dir = \"path\" !>main = \"file\" !>link = [\"lib\"] !>[test.dependencies] !>``` module fpm_manifest_test use fpm_manifest_dependency , only : new_dependencies use fpm_manifest_executable , only : executable_config_t use fpm_error , only : error_t , syntax_error , bad_name_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list implicit none private public :: test_config_t , new_test !> Configuation meta data for an test type , extends ( executable_config_t ) :: test_config_t contains !> Print information on this instance procedure :: info end type test_config_t contains !> Construct a new test configuration from a TOML data structure subroutine new_test ( self , table , error ) !> Instance of the test configuration type ( test_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve test name\" ) return end if if ( bad_name_error ( error , 'test' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"test\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_test !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) logical :: name_present integer :: ikey name_present = . false . call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Test section does not provide sufficient entries\" ) return end if do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in test entry\" ) exit case ( \"name\" ) name_present = . true . case ( \"source-dir\" , \"main\" , \"dependencies\" , \"link\" ) continue end select end do if ( allocated ( error )) return if (. not . name_present ) then call syntax_error ( error , \"Test name is not provided, please add a name entry\" ) end if end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the test configuration class ( test_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ii character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' , & & fmti = '(\"#\", 1x, a, t30, i0)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Test target\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % source_dir )) then if ( self % source_dir /= \"test\" . or . pr > 2 ) then write ( unit , fmt ) \"- source directory\" , self % source_dir end if end if if ( allocated ( self % main )) then if ( self % main /= \"main.f90\" . or . pr > 2 ) then write ( unit , fmt ) \"- test source\" , self % main end if end if if ( allocated ( self % dependency )) then if ( size ( self % dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- dependencies\" , size ( self % dependency ) end if do ii = 1 , size ( self % dependency ) call self % dependency ( ii )% info ( unit , pr - 1 ) end do end if end subroutine info end module fpm_manifest_test","tags":"","loc":"sourcefile/test.f90.html"},{"title":"Packaging and contributing – Fortran-lang/fpm","text":"","tags":"","loc":"page/index.html"},{"title":"Contributing Guidelines – Fortran-lang/fpm","text":"Contributing to the Fortran Package Manager Thank you for considering contributing to the Fortran Package Manager ( fpm ).\nPlease review and follow these guidelines to make the contribution process\nsimple and effective for all involved. It will help communicate that you\nrespect the time of the community developers. In return, the community will\nhelp address your problem, evaluate changes, and guide you through your pull\nrequests. By contributing to fpm , you certify that you own or are allowed to share the\ncontent of your contribution under the fpm license . Style Reporting a bug Suggesting a feature Workflow General guidelines For new contributors Style Please follow the Fortran stdlib style guide for any Fortran code that you contribute.\nThis allows us to focus on substance rather than style. Reporting a bug A bug is a demonstrable problem caused by the code in this repository.\nGood bug reports are extremely valuable to us—thank you! Before opening a bug report: Check if the issue has already been reported\n ( issues ). Check if it is still an issue or it has been fixed?\n Try to reproduce it with the latest version from the default branch. Isolate the problem and create a minimal test case. A good bug report should include all information needed to reproduce the bug.\nPlease be as detailed as possible: Which version of fpm are you using? Please be specific. What are the steps to reproduce the issue? What is the expected outcome? What happens instead? This information will help the community diagnose the issue quickly and with\nminimal back-and-forth. Suggesting a feature Before suggesting a new feature, take a moment to find out if it fits the scope\nof the project, or if it has already been discussed. It is up to you to provide\na strong argument to convince the community of the benefits of this feature.\nPlease provide as much detail and context as possible. If applicable, include a\nmocked-up snippet of what the output or behavior would look like with this\nfeature implemented. “Crazy”, out-of-the-box ideas are especially welcome.\nIt’s quite possible that we are not considering an unusually creative solution. Workflow fpm is a community project. There is no one single person making final\ndecisions. This is the workflow that we follow: Open a new issue to\n describe a bug or propose a new feature.\n Refer to the earlier sections on how to write a good bug report or feature\n request. Discuss with the community and reach majority consensus about what should be\n done about the bug or feature request.\n We define “majority” loosely as 80%.\n This means that at least 4 of 5 people engaged in the discussion should be\n able to agree on the next step.\n This allows us to have the community mostly agree while not getting stuck if\n one person disagrees.\n At this stage, the scope of the fix/feature, its behavior, and API if\n applicable should be defined.\n Only when you have community consensus on these items you should proceed to\n writing code and opening a PR. When actively working on code towards a PR, please assign yourself to the\n issue on GitHub. This is good collaborative practice to avoid duplicated effort and also\n inform others what you are currently working on. Open a new Pull Request (PR) with your contribution.\n The body of the PR should at least include a bullet-point summary of the\n changes, and a detailed description is encouraged.\n If the PR completely addresses the issue you opened in step 1, include in\n the PR description the following line: Fixes # . Request reviewers to your PR.\n For small bug fixes or documentation improvements, 1 to 2 reviewers is\n sufficient.\n For implementation of bigger features, request 3 to 4 or more reviewers.\n Ideally, request reviewers that participated in step 2. If your PR implements a feature that adds or changes the behavior of fpm ,\n your PR must also include appropriate changes to the documentation. This workflow can evolve and change over time as we learn how best to work\ntogether. If you have an idea on how to improve the workflow itself, please\nopen an issue and we’ll discuss it. General guidelines A PR should implement only one feature or bug fix. Do not commit changes to files that are irrelevant to your feature or bug fix. Smaller PRs are better than large PRs, and will lead to a shorter review and\n merge cycle Add tests for your feature or bug fix to be sure that it stays functional and useful Be open to constructive criticism and requests for improving your code. Again, please follow the Fortran stdlib style guide . For new contributors If you have never created a pull request before, welcome :tada:.\nYou can learn how from this great tutorial . Don’t know where to start?\nYou can start by looking through the list of open issues .","tags":"","loc":"page/Contributing.html"},{"title":"License – Fortran-lang/fpm","text":"MIT License Copyright (c) 2020 fpm contributors Permission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the “Software”), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","tags":"","loc":"page/License.html"},{"title":"Manifest reference – Fortran-lang/fpm","text":"301 - Moved This document now lives at https://fpm.fortran-lang.org/spec/manifest.html","tags":"","loc":"page/Manifest.html"},{"title":"Packaging with fpm – Fortran-lang/fpm","text":"Preparing your package for FPM This document describes how you need to organize your application or library for\nit to successfully build with the Fortran Package Manager ( fpm ). What kind of package can fpm build? Example package layouts Single program Single-module library Multi-module library Application and library Multi-level library Be more explicit Add some tests Adding dependencies Custom build scripts What kind of package can fpm build? You can use fpm to build: Applications (program only) Libraries (modules only) Combination of the two (programs and modules combined) Let’s look at some examples of different kinds of package layouts that you can\nuse with fpm . Example package layouts This section describes some example package layouts that you can build with fpm . You can use them to model the layout of your own package. Single program Let’s start with the simplest package imaginable—a single program without\ndependencies or modules. Here’s what the layout of the top-level directory\nlooks like: .\n├── app\n│   └── main.f90\n└── fpm.toml We have one source file ( main.f90 ) in one directory ( app ). Its contents\nare: program main print * , 'Hello, World!' end program main This program prints the usual greeting to the standard output, and nothing more. There’s another important file in the top-level directory, fpm.toml . This is fpm ’s configuration file specific to your package. It includes all the data\nthat fpm needs to build your app. In our simple case, it looks like this: name = \"hello\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" The preamble includes some metadata, such as license , author , and similar,\nthat you may have seen in other package manager configuration files. The one\noption that matters here right now is: name = \"hello\" This line specifies the name of your package, which determines the name of the\nexecutable file of your program. In this example, our program executable, once\nbuilt, will be called hello . Let’s now build this program using fpm : $ fpm build # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/hello) On the first line, we ran fpm build to compile and link the application.\nThe latter two lines are emitted by fpm , and indicate which command was\nexecuted at each build step ( gfortran ), and which files have been output\nby it: object file main.o , and executable hello . We can now run the app with fpm run : $ fpm run Hello, World! If your application needs to use a module internally, but you don’t intend\nto build it as a library to be used in other projects, you can include the\nmodule in your program source file as well.\nFor example: $ cat app / main . f90 module math_constants real , parameter :: pi = 4 * atan ( 1. ) end module math_constants program main use math_constants , only : pi print * , 'Hello, World!' print * , 'pi = ' , pi end program main Now, run this using fpm run : $ fpm run # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/hello) Hello, World! pi = 3 .14159274 Although we have named our program hello , which is the same name as the\npackage name in fpm.toml , you can name it anything you want as long as it’s\npermitted by the language. Notice that you can run fpm run , and if the package hasn’t been built yet, fpm build will run automatically for you. This is true if the source files\nhave been updated since the last build. Thus, if you want to run your\napplication, you can skip the fpm build step, and go straight to fpm run . When running your application using fpm run , the program’s exit code is\npassed by fpm back to the operating system. So, it is possible to use Fortran\nnumbered stop and error stop codes to pass termination reasons back to the terminal. Try running the following app with fpm run : program main use math_constants , only : pi real :: angle read ( * , * , iostat = ierr ) angle if ( ierr /= 0 ) then stop 2 ! Not real elseif ( angle > pi ) then stop 1 else stop 0 endif end program main and then checking that the error code matches. Note that error codes are passed to variable $? on Unix/Mac systems, and to environment variable %errorlevel% on Windows. In this last example, our source file defined a math_constants module inside\nthe same source file as the main program. Let’s see how we can define an fpm package that makes this module available as a library. Single-module library The package layout for this example looks like this: . ├── fpm . toml └── src └── math_constants . f90 In this example we’ll build a simple math constants library that exports\nthe number pi as a parameter: $ cat src / math_constants . f90 module math_constants real , parameter :: pi = 4 * atan ( 1. ) end module math_constants and our fpm.toml is the same as before. Now use fpm build to build the package: $ fpm build # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a Based on the output of fpm build , fpm first ran gfortran to emit the\nbinary object ( math_constants.o ) and module ( math_constants.mod ) files.\nThen it ran ar to create a static library archive math_constants.a . build/debug/library is thus both your include and library path, should you\nwant to compile and link an external program with this library. For modules in the top-level ( src ) directory, fpm requires that: The module has the same name as the source file. There is only one module per file. These two requirements simplify the build process for fpm . As Fortran\ncompilers emit module files ( .mod ) with the same name as the module itself\n(but not the source file, .f90 ), naming the module the same as the source file\nallows fpm to: Uniquely and exactly map a source file ( .f90 ) to its object ( .o ) and\nmodule ( .mod ) files. Avoid conflicts with modules of the same name that could appear in dependency\npackages (more on this in a bit). Since this is a library without executable programs, fpm run here does\nnothing. In this example, our library is made of only one module. However, most\nreal-world libraries are likely to use multiple modules. Let’s see how you can\npackage your multi-module library. Multi-module library In this example, we’ll use another module to define a 64-bit real kind\nparameter and make it available in math_constants to define pi with\nhigher precision. To make this exercise worthwhile, we’ll define another math\nconstant, Euler’s number. Our package layout looks like this: . ├── fpm . toml └── src ├── math_constants . f90 └── type_kinds . f90 And our source file contents are: $ cat src / math_constants . f90 module math_constants use type_kinds , only : rk real ( rk ), parameter :: pi = 4 * atan ( 1._rk ) real ( rk ), parameter :: e = exp ( 1._rk ) end module math_constants $ cat src / type_kinds . f90 module type_kinds use iso_fortran_env , only : real64 integer , parameter :: rk = real64 end module type_kinds and there are no changes to our fpm.toml relative to previous examples. Like before, notice that the module type_kinds is name exactly as the\nsource file that contains it.\nThis is important. By now you know how to build the package: $ fpm build # gfortran (for build/debug/library/type_kinds.o build/debug/library/type_kinds.mod) # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a Our build path now contains: $ ls build/debug/library/\nmath_constants.a math_constants.mod math_constants.o type_kinds.mod type_kinds.o And the static library includes all the object files: $ nm build/debug/library/math_constants.a\n\nmath_constants.o:\n\ntype_kinds.o: The takeaways from this example are that: fpm automatically scanned the src directory for any source files. It also resolved the dependency order between different modules. Application and library Let’s now combine the two previous examples into one: We’ll build the math\nconstants library and an executable program that uses it. We’ll use this\nprogram as a demo, and to verify that defining higher-precision constants from\nthe previous example actually worked. Here’s the package layout for your application + library package: . ├── app │ └── main . f90 ├── fpm . toml └── src ├── math_constants . f90 └── type_kinds . f90 Our fpm.toml remains unchanged and our executable program source file is: $ cat app / main . f90 program main use math_constants , only : e , pi print * , 'math_constants library demo' print * , 'pi = ' , pi print * , 'e = ' , e end program main Let’s go straight to running the demo program: $ fpm run # gfortran (for build/debug/library/type_kinds.o build/debug/library/type_kinds.mod) # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/math_constants) math_constants library demo pi = 3 .1415926535897931 e = 2 .7182818284590451 The fpm build + run process works as expected, and our program correctly\noutputs higher-precision constants. So far we covered how fpm builds: A single program A single-module library A multi-module library A program and a library However, all our modules so far have been organized in the top level source\ndirectory. More complex libraries may organize their modules in subdirectories.\nLet’s see how we can build this with fpm . Multi-level library In this example, we’ll define our library as a collection of modules, two of\nwhich are defined in a subdirectory: . ├── app │ └── main . f90 ├── fpm . toml └── src ├── math_constants │ ├── derived . f90 │ └── fundamental . f90 ├── math_constants . f90 └── type_kinds . f90 First, fpm.toml and src/type_kinds.f90 remain unchanged relative to the\nprevious example. The rest of the source files are: $ cat src / math_constants . f90 module math_constants use math_constants_fundamental , only : e , pi use math_constants_derived , only : half_pi , two_pi end module math_constants $ cat src / math_constants / fundamental . f90 module math_constants_fundamental use type_kinds , only : rk real ( rk ), parameter :: pi = 4 * atan ( 1._rk ) real ( rk ), parameter :: e = exp ( 1._rk ) end module math_constants_fundamental $ cat src / math_constants / derived . f90 module math_constants_derived use math_constants_fundamental , only : pi use type_kinds , only : rk real ( rk ), parameter :: two_pi = 2 * pi real ( rk ), parameter :: half_pi = pi / 2 end module math_constants_derived $ cat app / main . f90 program main use math_constants , only : e , pi , half_pi , two_pi print * , 'math_constants library demo' print * , 'pi = ' , pi print * , '2*pi = ' , two_pi print * , 'pi/2 = ' , half_pi print * , 'e = ' , e end program main Our top-level math_constants module now doesn’t define the constants, but\nimports them from the two modules in the subdirectory. Constants e and pi we define in the math_constants_fundamental module, and two_pi and half_pi in the math_constants_derived module. From the main program, we access all\nthe constants from the top-level module math_constants . Let’s build and run this package: $ fpm run # gfortran (for build/debug/library/type_kinds.o build/debug/library/type_kinds.mod) # gfortran (for build/debug/library/math_constants_fundamental.o build/debug/library/math_constants_fundamental.mod) # gfortran (for build/debug/library/math_constants_derived.o build/debug/library/math_constants_derived.mod) # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/math_constants) math_constants library demo pi = 3 .1415926535897931 2 *pi = 6 .2831853071795862 pi/2 = 1 .5707963267948966 e = 2 .7182818284590451 Again, fpm built and run the package as expected. Recall from an earlier example that fpm required the modules in the top-level src directory to be named the same as their source file. This is why src/math_constants.f90 defines module math_constants . For modules defined in subdirectories, there’s an additional requirement: module\nname must contain the path components of the directory that its source file is\nin. In our case, src/math_constants/fundamental.f90 defines the math_constants_fundamental module. Likewise, src/math_constants/derived.f90 defines the math_constants_derived module. This rule applies generally to any number of nested directories and modules.\nFor example, src/a/b/c/d.f90 must define a module called a_b_c_d . Takeaways from this example are that: You can place your module source files in any levels of subdirectories inside src . The module name must include the path components and the source file name–for example, src/a/b/c/d.f90 must define a module called a_b_c_d . Be more explicit So far we’ve let fpm use its defaults to determine the layout of our package.\nIt determined where our library sources would live, what the name of the\nexecutable will be, and some other things. But we can be more explicit about it,\nand make some changes to those things. Let’s look at what the fpm.toml file from our last example would look like if\nwe specified everything. name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" You can see that by making these explicit in the fpm.toml we are able to\nchange many of the settings that fpm used by default. We can change the\nfolders where our sources are stored, we can change the name of our executable,\nand we can change the name of the file our program is defined in. Add some tests fpm also provides support for unit testing. By default, fpm looks for a\nprogram in test/main.f90 which it will compile and execute with the command fpm test . The tests are treated pretty much exactly like the executables.\nLet’s define one explicitly in our fpm.toml file. We’ll make sure that our\ndefinition of pi satisfies the property sin(pi) == 0.0 . Here’s the fpm.toml file: name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" [[ test ]] name = \"runTests\" source-dir = \"test\" main = \"main.f90\" where the contents of the main.f90 file are program main use math_constants , only : pi print * , \"sin(pi) = \" , sin ( pi ) end program main With this setup, we can run our tests. $ fpm test # gfortran (for build/debug/library/type_kinds.o build/debug/library/type_kinds.mod) # gfortran (for build/debug/library/math_constants_fundamental.o build/debug/library/math_constants_fundamental.mod) # gfortran (for build/debug/library/math_constants_derived.o build/debug/library/math_constants_derived.mod) # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/math_constants) # gfortran (for build/debug/test/main.o) # gfortran (for build/debug/test/runTests) sin ( pi ) = 1 .2246467991473532E-016 Adding dependencies Inevitably, you’ll want to be able to include other libraries in your project.\nfpm makes this incredibly simple, by taking care of fetching and compiling your\ndependencies for you. You just tell it what your dependencies are, and where to\nfind them. Let’s add a dependency to our library. Now our fpm.toml file looks\nlike this: name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [dependencies] helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" [[ test ]] name = \"runTests\" source-dir = \"test\" main = \"main.f90\" Now you can use any modules from this library anywhere in your code. Just like\nthis: program main use helloff , only : create_greeting use math_constants , only : e , pi , half_pi , two_pi print * , 'math_constants library demo' print * , 'pi = ' , pi print * , '2*pi = ' , two_pi print * , 'pi/2 = ' , half_pi print * , 'e = ' , e print * , create_greeting ( \"fpm\" ) end program main And now, fpm run will output the following: math_constants library demo pi = 3.1415926535897931 2 * pi = 6.2831853071795862 pi / 2 = 1.5707963267948966 e = 2.7182818284590451 Hello , fpm ! Additionally, any users of your library will now automatically depend on your\ndependencies too. So if you don’t need that dependency for the library, like in\nthe above example, then you can specify it for the specific executable like\nbelow. Then fpm will still fetch and compile it when building your executable,\nbut users of your library won’t have to. name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" [executable.dependencies] helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } [[ test ]] name = \"runTests\" source-dir = \"test\" main = \"main.f90\" You can also specify dependencies for your tests in a similar way, with [test.dependencies] instead of [executable.dependencies] . There’s also\nanother option for test dependencies. The below example makes the dependencies\navailable for all the tests, but again your users won’t depend on these. name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [dev-dependencies] helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" [[ test ]] name = \"runTests\" source-dir = \"test\" main = \"main.f90\" You can also be specific about which version of a dependency you’d like. You can\nspecify a branch to use like helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\", branch = \"master\" } ,\nor a tag like helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\", tag = \"v1.2.3\" } ,\nor even a specific commit like helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\", rev = \"a1b2c3\" } .\nYou can even specify the path to another folder, if for example you’ve got\nanother fpm package in the same repository. Like this: helloff = { path = \"helloff\" } . Note that you should not specify paths\noutside of your repository, or things won’t work for your users. Custom build scripts If there is something special about your library that makes fpm unable to build\nit, you can provide your own build script. fpm will then simply call your build\nscript to build the library. To specify a build script to be used, put it in the library section of your fpm.toml file, like: [library] source-dir = \"src\" build-script = \"my_build_script\" fpm will set the following environment variables to specify some parameters to\nthe build script: FC – The Fortran compiler to be used. FFLAGS – The flags that should be passed to the Fortran compiler. BUILD_DIR – Where the compiled files should be placed. INCLUDE_DIRS – The folders where any dependencies can be found, space separated.\nIt is then the responsibility of the build script to generate the appropriate\ninclude flags. Additionally, script will be called with the name of the archive ( *.a file)\nthat should be produced as the command line argument. Note: If the name of the build script is Makefile or ends with .mk , then\nthe make program will be used to run it. Not the the archive file is explicitly\nspecified as the target to be built Note: All file and directory names are specified with their full canonical\npath.","tags":"","loc":"page/Packaging.html"}]} \ No newline at end of file +var tipuesearch = {"pages":[{"title":" Fortran-lang/fpm ","text":"Fortran-lang/fpm Fortran package manager developer documentation The package manifest Command line interface The package model The build backend Generating this documentation Fortran package manager developer documentation This is the main documentation of the Fortran package manager ( fpm ).\nThis document serves as developer documentation of fpm itself and contains general advice for developing in the fpm code base. The package manifest The central object describing an fpm project is the package manifest fpm.toml .\nThe manifest is written in TOML, you can find the TOML specification at the official TOML homepage . The fpm.toml file targets project developers and maintainers to relieve them from writing build files for their packages.\nWith the package manifest a central place to collect information about the project is provided.\nIt contains the versioning and licensing meta data, as well as the information on external dependencies and the required build-tools or compiler settings. The manifest format specific to fpm projects is documented in the manifest reference . Note For a more practical but less complete guide on creating fpm projects see the packaging guide . The details of the TOML parsing are implemented with using the tomlf module.\nGenerally, the interface to all TOML related functions for fpm is found in the proxy module fpm_toml . All the manifest types are bundled in fpm_manifest .\nWhile the specific subtables for the package configuration are found in the src/fpm/manifest directory, they should be reexported in the fpm_manifest module if they should be elsewhere in fpm . Command line interface fpm is mainly used as a command line tool.\nTo work with an fpm project as a user you can completely rely on the command line. The command line interface is build with the M_CLI2 module and can be found in fpm_command_line . The package model Once front-end inputs have been received from the package manifest and command line interface, fpm will construct an\ninternal representation of the package and its dependencies. This internal representation is known as the package model .\nThe model and its associated data types should encapsulate all the information required to correctly build a package and\nshould be independent of the intended backend build system. Information stored in the model includes: build targets and\ntheir inter-dependencies; compiler and compiler flags; library linking information. For more information on the contents of the package model and the process for constructing it, please see fpm_model . The build backend Once a complete package model has been constructed, it can be passed to a backend for either performing the compilation\nand linking of targets, or for generating configuration files for a third-party build system.\nCurrently, only a native backend is implemented in fpm . See fpm_backend for more information. Generating this documentation This documentation is generated by FORD .\nFor more details on the project file and the comment markup in the source code visit the FORD documentation . To regenerate this documentation run: ford docs.md Developer Info fortran-lang/fpm contributors","tags":"home","loc":"index.html"},{"title":"build_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: build_config_t Configuration data for build Components Type Visibility Attributes Name Initial logical, public :: auto_examples = .true. Automatic discovery of examples logical, public :: auto_executables = .true. Automatic discovery of executables logical, public :: auto_tests = .true. Automatic discovery of tests type( string_t ), public, allocatable :: external_modules (:) External modules to use type( string_t ), public, allocatable :: link (:) Libraries to link against logical, public :: module_naming = .false. Enforcing of package module names type( string_t ), public :: module_prefix Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump build config to toml table Arguments Type Intent Optional Attributes Name class( build_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on build configuration instance Arguments Type Intent Optional Attributes Name class( build_config_t ), intent(in) :: self Instance of the build configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read build config from toml table (no checks made at this stage) Module naming: fist, attempt boolean value first\nValue found, but not a boolean. Attempt to read a prefix string Arguments Type Intent Optional Attributes Name class( build_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => build_conf_is_same Serialization interface private function build_conf_is_same(this, that) Check that two dependency trees are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( build_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: build_config_t !> Automatic discovery of executables logical :: auto_executables = . true . !> Automatic discovery of examples logical :: auto_examples = . true . !> Automatic discovery of tests logical :: auto_tests = . true . !> Enforcing of package module names logical :: module_naming = . false . type ( string_t ) :: module_prefix !> Libraries to link against type ( string_t ), allocatable :: link (:) !> External modules to use type ( string_t ), allocatable :: external_modules (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => build_conf_is_same procedure :: dump_to_toml procedure :: load_from_toml end type build_config_t","tags":"","loc":"type/build_config_t.html"},{"title":"install_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: install_config_t Configuration data for installation Components Type Visibility Attributes Name Initial logical, public :: library = .false. Install library with this project Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Arguments Type Intent Optional Attributes Name class( install_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on install configuration instance Arguments Type Intent Optional Attributes Name class( install_config_t ), intent(in) :: self Instance of the build configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( install_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => install_conf_same Serialization interface private function install_conf_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( install_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: install_config_t !> Install library with this project logical :: library = . false . contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => install_conf_same procedure :: dump_to_toml procedure :: load_from_toml end type install_config_t","tags":"","loc":"type/install_config_t.html"},{"title":"dependency_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: dependency_config_t Configuration meta data for a dependency Components Type Visibility Attributes Name Initial type( git_target_t ), public, allocatable :: git Git descriptor character(len=:), public, allocatable :: name Name of the dependency character(len=:), public, allocatable :: namespace Namespace which the dependency belongs to.\nEnables multiple dependencies with the same name.\nRequired for dependencies that are obtained via the official registry. character(len=:), public, allocatable :: path Local target type( preprocess_config_t ), public, allocatable :: preprocess (:) Requested macros for the dependency type( version_t ), public, allocatable :: requested_version The requested version of the dependency.\nThe latest version is used if not specified. Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(in) :: self Instance of the dependency configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => dependency_is_same Serialization interface private function dependency_is_same(this, that) Check that two dependency configs are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: dependency_config_t !> Name of the dependency character ( len = :), allocatable :: name !> Local target character ( len = :), allocatable :: path !> Namespace which the dependency belongs to. !> Enables multiple dependencies with the same name. !> Required for dependencies that are obtained via the official registry. character ( len = :), allocatable :: namespace !> The requested version of the dependency. !> The latest version is used if not specified. type ( version_t ), allocatable :: requested_version !> Requested macros for the dependency type ( preprocess_config_t ), allocatable :: preprocess (:) !> Git descriptor type ( git_target_t ), allocatable :: git contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => dependency_is_same procedure :: dump_to_toml procedure :: load_from_toml end type dependency_config_t","tags":"","loc":"type/dependency_config_t.html"},{"title":"version_t – Fortran-lang/fpm ","text":"type, public :: version_t Type-Bound Procedures generic, public :: operator(.match.) => match Compare a version against a version constraint (x.x.0 <= v < x.x.HUGE) private elemental function match(lhs, rhs) Try to match first version against second version Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical Version match following semantic versioning rules generic, public :: operator(/=) => not_equals private elemental function not_equals(lhs, rhs) result(not_equal) Check two versions for inequality Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical Version mismatch generic, public :: operator(<) => less private elemental function less(lhs, rhs) result(is_less) Relative comparison of two versions Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical First version is less generic, public :: operator(<=) => less_equals private elemental function less_equals(lhs, rhs) result(is_less_equal) Relative comparison of two versions Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical First version is less or equal generic, public :: operator(==) => equals private elemental function equals(lhs, rhs) result(is_equal) Check to version numbers for equality Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical Version match generic, public :: operator(>) => greater private elemental function greater(lhs, rhs) result(is_greater) Relative comparison of two versions Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical First version is greater generic, public :: operator(>=) => greater_equals private elemental function greater_equals(lhs, rhs) result(is_greater_equal) Relative comparison of two versions Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: lhs First version number class( version_t ), intent(in) :: rhs Second version number Return Value logical First version is greater or equal procedure, public :: s Create a printable string from a version data type private pure function s(self) result(string) Arguments Type Intent Optional Attributes Name class( version_t ), intent(in) :: self Version number Return Value character(len=:), allocatable Character representation of the version Source Code type :: version_t private !> Version numbers found integer , allocatable :: num (:) contains generic :: operator ( == ) => equals procedure , private :: equals generic :: operator ( /= ) => not_equals procedure , private :: not_equals generic :: operator ( > ) => greater procedure , private :: greater generic :: operator ( < ) => less procedure , private :: less generic :: operator ( >= ) => greater_equals procedure , private :: greater_equals generic :: operator ( <= ) => less_equals procedure , private :: less_equals !> Compare a version against a version constraint (x.x.0 <= v < x.x.HUGE) generic :: operator (. match .) => match procedure , private :: match !> Create a printable string from a version data type procedure :: s end type version_t","tags":"","loc":"type/version_t.html"},{"title":"enum_descriptor – Fortran-lang/fpm ","text":"type, public :: enum_descriptor Possible git target Components Type Visibility Attributes Name Initial integer, public :: branch = 201 Branch in git repository integer, public :: default = 200 Default target integer, public :: error = -999 Invalid descriptor integer, public :: revision = 203 Commit hash integer, public :: tag = 202 Tag in git repository Source Code type :: enum_descriptor !> Default target integer :: default = 200 !> Branch in git repository integer :: branch = 201 !> Tag in git repository integer :: tag = 202 !> Commit hash integer :: revision = 203 !> Invalid descriptor integer :: error = - 999 end type enum_descriptor","tags":"","loc":"type/enum_descriptor.html"},{"title":"git_target_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: git_target_t Description of an git target Components Type Visibility Attributes Name Initial integer, public :: descriptor = git_descriptor%default Kind of the git target character(len=:), public, allocatable :: object Additional descriptor of the git object character(len=:), public, allocatable :: url Target URL of the git repository Type-Bound Procedures procedure, public :: checkout Fetch and checkout in local directory public subroutine checkout (self, local_path, error) Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target character(len=*), intent(in) :: local_path Local path to checkout in type( error_t ), intent(out), allocatable :: error Error generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml public subroutine dump_to_toml (self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Show information on instance public subroutine info (self, unit, verbosity) Show information on git target Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml public subroutine load_from_toml (self, table, error) Read dependency from toml table (no checks made at this stage) Read more… Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => git_is_same Serialization interface public function git_is_same (this, that) Check that two git targets are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: git_target_t !> Kind of the git target integer :: descriptor = git_descriptor % default !> Target URL of the git repository character ( len = :), allocatable :: url !> Additional descriptor of the git object character ( len = :), allocatable :: object contains !> Fetch and checkout in local directory procedure :: checkout !> Show information on instance procedure :: info !> Serialization interface procedure :: serializable_is_same => git_is_same procedure :: dump_to_toml procedure :: load_from_toml end type git_target_t","tags":"","loc":"type/git_target_t.html"},{"title":"installer_t – Fortran-lang/fpm ","text":"type, public :: installer_t Declaration of the installer type Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: bindir Binary dir relative to the installation prefix character(len=:), public, allocatable :: copy Command to copy objects into the installation prefix character(len=:), public, allocatable :: includedir Include directory relative to the installation prefix character(len=:), public, allocatable :: libdir Library directory relative to the installation prefix character(len=:), public, allocatable :: move Command to move objects into the installation prefix integer, public :: os Cached operating system character(len=:), public, allocatable :: prefix Path to installation directory integer, public :: unit = output_unit Output unit for informative printout integer, public :: verbosity = 1 Verbosity of the installer Type-Bound Procedures procedure, public :: install Install a generic file into a subdirectory in the installation prefix private subroutine install(self, source, destination, error) Install a generic file into a subdirectory in the installation prefix Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: source Path to the original file character(len=*), intent(in) :: destination Path to the destination inside the prefix type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: install_executable Install an executable in its correct subdirectory private subroutine install_executable(self, executable, error) Install an executable in its correct subdirectory Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: executable Path to the executable type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: install_header Install a header/module in its correct subdirectory private subroutine install_header(self, header, error) Install a header/module in its correct subdirectory Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: header Path to the header type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: install_library Install a library in its correct subdirectory private subroutine install_library(self, library, error) Install a library in its correct subdirectory Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: library Path to the library type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: make_dir Create a new directory in the prefix, type-bound for unit testing purposes private subroutine make_dir(self, dir, error) Create a new directory in the prefix Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: dir Directory to be created type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: run Run an installation command, type-bound for unit testing purposes private subroutine run(self, command, error) Run an installation command Arguments Type Intent Optional Attributes Name class( installer_t ), intent(inout) :: self Instance of the installer character(len=*), intent(in) :: command Command to be launched type( error_t ), intent(out), allocatable :: error Error handling Source Code type :: installer_t !> Path to installation directory character ( len = :), allocatable :: prefix !> Binary dir relative to the installation prefix character ( len = :), allocatable :: bindir !> Library directory relative to the installation prefix character ( len = :), allocatable :: libdir !> Include directory relative to the installation prefix character ( len = :), allocatable :: includedir !> Output unit for informative printout integer :: unit = output_unit !> Verbosity of the installer integer :: verbosity = 1 !> Command to copy objects into the installation prefix character ( len = :), allocatable :: copy !> Command to move objects into the installation prefix character ( len = :), allocatable :: move !> Cached operating system integer :: os contains !> Install an executable in its correct subdirectory procedure :: install_executable !> Install a library in its correct subdirectory procedure :: install_library !> Install a header/module in its correct subdirectory procedure :: install_header !> Install a generic file into a subdirectory in the installation prefix procedure :: install !> Run an installation command, type-bound for unit testing purposes procedure :: run !> Create a new directory in the prefix, type-bound for unit testing purposes procedure :: make_dir end type installer_t","tags":"","loc":"type/installer_t.html"},{"title":"package_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: package_config_t Package meta data Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: author Author meta data type( build_config_t ), public :: build Build configuration data character(len=:), public, allocatable :: copyright Copyright meta data type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data type( dependency_config_t ), public, allocatable :: dev_dependency (:) Development dependency meta data type( example_config_t ), public, allocatable :: example (:) Example meta data type( executable_config_t ), public, allocatable :: executable (:) Executable meta data type( fortran_config_t ), public :: fortran Fortran meta data type( install_config_t ), public :: install Installation configuration data type( library_config_t ), public, allocatable :: library Library meta data character(len=:), public, allocatable :: license License meta data character(len=:), public, allocatable :: maintainer Maintainer meta data type( metapackage_config_t ), public :: meta Metapackage data character(len=:), public, allocatable :: name Name of the package type( preprocess_config_t ), public, allocatable :: preprocess (:) Preprocess meta data type( profile_config_t ), public, allocatable :: profiles (:) Profiles meta data type( test_config_t ), public, allocatable :: test (:) Test meta data type( version_t ), public :: version Package version Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump manifest to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nDuplicate profile names are possible, as multiple profiles are possible with the\nsame name, same compiler, etc. So, use a unique name here\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep\nBecause dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( package_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( package_config_t ), intent(in) :: self Instance of the package configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read manifest from toml table (no checks made at this stage) Read all packages\nRead all packages\nRead all packages\nRead all packages\nRead all packages\nRead all packages\nRead all packages Arguments Type Intent Optional Attributes Name class( package_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => manifest_is_same Serialization interface private function manifest_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( package_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: package_config_t !> Name of the package character ( len = :), allocatable :: name !> Package version type ( version_t ) :: version !> Build configuration data type ( build_config_t ) :: build !> Metapackage data type ( metapackage_config_t ) :: meta !> Installation configuration data type ( install_config_t ) :: install !> Fortran meta data type ( fortran_config_t ) :: fortran !> License meta data character ( len = :), allocatable :: license !> Author meta data character ( len = :), allocatable :: author !> Maintainer meta data character ( len = :), allocatable :: maintainer !> Copyright meta data character ( len = :), allocatable :: copyright !> Library meta data type ( library_config_t ), allocatable :: library !> Executable meta data type ( executable_config_t ), allocatable :: executable (:) !> Dependency meta data type ( dependency_config_t ), allocatable :: dependency (:) !> Development dependency meta data type ( dependency_config_t ), allocatable :: dev_dependency (:) !> Profiles meta data type ( profile_config_t ), allocatable :: profiles (:) !> Example meta data type ( example_config_t ), allocatable :: example (:) !> Test meta data type ( test_config_t ), allocatable :: test (:) !> Preprocess meta data type ( preprocess_config_t ), allocatable :: preprocess (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => manifest_is_same procedure :: dump_to_toml procedure :: load_from_toml end type package_config_t","tags":"","loc":"type/package_config_t.html"},{"title":"serializable_t – Fortran-lang/fpm ","text":"type, public, abstract :: serializable_t An abstract interface for any fpm class that should be fully serializable to/from TOML/JSON Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure(to_toml), public, deferred :: dump_to_toml Dump to TOML table, unit, file subroutine to_toml(self, table, error) Prototype Write object to TOML datastructure Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure(from_toml), public, deferred :: load_from_toml Load from TOML table, unit, file subroutine from_toml(self, table, error) Prototype Read dependency tree from TOML data structure Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure(is_equal), public, deferred :: serializable_is_same Serializable entities need a way to check that they’re equal function is_equal(this, that) Prototype Compare two serializable objects Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , abstract , public :: serializable_t contains !> Dump to TOML table, unit, file procedure ( to_toml ), deferred :: dump_to_toml procedure , non_overridable , private :: dump_to_file procedure , non_overridable , private :: dump_to_unit generic :: dump => dump_to_toml , dump_to_file , dump_to_unit !> Load from TOML table, unit, file procedure ( from_toml ), deferred :: load_from_toml procedure , non_overridable , private :: load_from_file procedure , non_overridable , private :: load_from_unit generic :: load => load_from_toml , load_from_file , load_from_unit !> Serializable entities need a way to check that they're equal procedure ( is_equal ), deferred :: serializable_is_same generic :: operator ( == ) => serializable_is_same !> Test load/write roundtrip procedure , non_overridable :: test_serialization end type serializable_t","tags":"","loc":"type/serializable_t.html"},{"title":"file_scope_flag – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: file_scope_flag Type storing file name - file scope compiler flags pairs Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: file_name Name of the file character(len=:), public, allocatable :: flags File scope flags Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => file_scope_dump public subroutine file_scope_dump (self, table, error) Dump to toml table Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => file_scope_load public subroutine file_scope_load (self, table, error) Read from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => file_scope_same Serialization interface public function file_scope_same (this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: file_scope_flag !> Name of the file character ( len = :), allocatable :: file_name !> File scope flags character ( len = :), allocatable :: flags contains !> Serialization interface procedure :: serializable_is_same => file_scope_same procedure :: dump_to_toml => file_scope_dump procedure :: load_from_toml => file_scope_load end type file_scope_flag","tags":"","loc":"type/file_scope_flag.html"},{"title":"profile_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: profile_config_t Configuration meta data for a profile Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: c_flags C compiler flags character(len=:), public, allocatable :: compiler Name of the compiler character(len=:), public, allocatable :: cxx_flags C++ compiler flags type( file_scope_flag ), public, allocatable :: file_scope_flags (:) File scope flags character(len=:), public, allocatable :: flags Fortran compiler flags logical, public :: is_built_in = .false. Is this profile one of the built-in ones? character(len=:), public, allocatable :: link_time_flags Link time compiler flags integer, public :: os_type = OS_ALL Value repesenting OS character(len=:), public, allocatable :: profile_name Name of the profile Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => profile_dump public subroutine profile_dump (self, table, error) Dump to toml table Read more… Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance public subroutine info (self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: self Instance of the profile configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => profile_load public subroutine profile_load (self, table, error) Read from toml table (no checks made at this stage) Read more… Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => profile_same Serialization interface public function profile_same (this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: profile_config_t !> Name of the profile character ( len = :), allocatable :: profile_name !> Name of the compiler character ( len = :), allocatable :: compiler !> Value repesenting OS integer :: os_type = OS_ALL !> Fortran compiler flags character ( len = :), allocatable :: flags !> C compiler flags character ( len = :), allocatable :: c_flags !> C++ compiler flags character ( len = :), allocatable :: cxx_flags !> Link time compiler flags character ( len = :), allocatable :: link_time_flags !> File scope flags type ( file_scope_flag ), allocatable :: file_scope_flags (:) !> Is this profile one of the built-in ones? logical :: is_built_in = . false . contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => profile_same procedure :: dump_to_toml => profile_dump procedure :: load_from_toml => profile_load end type profile_config_t","tags":"","loc":"type/profile_config_t.html"},{"title":"build_progress_t – Fortran-lang/fpm ","text":"type, public :: build_progress_t Build progress object Components Type Visibility Attributes Name Initial type( console_t ), public :: console Console object for updating console lines integer, public :: n_complete Number of completed targets integer, public :: n_target Total number of targets scheduled integer, public, allocatable :: output_lines (:) Store needed when updating previous console lines logical, public :: plain_mode = .true. ‘Plain’ output (no colors or updating) type( build_target_ptr ), public, pointer :: target_queue (:) Queue of scheduled build targets Constructor public interface build_progress_t Constructor for build_progress_t private function new_build_progress(target_queue, plain_mode) result(progress) Initialise a new build progress object Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in), target :: target_queue (:) The queue of scheduled targets logical, intent(in), optional :: plain_mode Enable ‘plain’ output for progress object Return Value type( build_progress_t ) Progress object to initialise Type-Bound Procedures procedure, public :: compiling_status => output_status_compiling Output ‘compiling’ status for build target private subroutine output_status_compiling(progress, queue_index) Output ‘compiling’ status for build target and overall percentage progress Arguments Type Intent Optional Attributes Name class( build_progress_t ), intent(inout) :: progress Progress object integer, intent(in) :: queue_index Index of build target in the target queue procedure, public :: completed_status => output_status_complete Output ‘complete’ status for build target private subroutine output_status_complete(progress, queue_index, build_stat) Output ‘complete’ status for build target and update overall percentage progress Arguments Type Intent Optional Attributes Name class( build_progress_t ), intent(inout) :: progress Progress object integer, intent(in) :: queue_index Index of build target in the target queue integer, intent(in) :: build_stat Build status flag procedure, public :: success => output_progress_success Output finished status for whole package private subroutine output_progress_success(progress) Output finished status for whole package Arguments Type Intent Optional Attributes Name class( build_progress_t ), intent(inout) :: progress Source Code type build_progress_t !> Console object for updating console lines type ( console_t ) :: console !> Number of completed targets integer :: n_complete !> Total number of targets scheduled integer :: n_target !> 'Plain' output (no colors or updating) logical :: plain_mode = . true . !> Store needed when updating previous console lines integer , allocatable :: output_lines (:) !> Queue of scheduled build targets type ( build_target_ptr ), pointer :: target_queue (:) contains !> Output 'compiling' status for build target procedure :: compiling_status => output_status_compiling !> Output 'complete' status for build target procedure :: completed_status => output_status_complete !> Output finished status for whole package procedure :: success => output_progress_success end type build_progress_t","tags":"","loc":"type/build_progress_t.html"},{"title":"build_target_ptr – Fortran-lang/fpm ","text":"type, public :: build_target_ptr Wrapper type for constructing arrays of [[build_target_t]] pointers Components Type Visibility Attributes Name Initial type( build_target_t ), public, pointer :: ptr => null() Source Code type build_target_ptr type ( build_target_t ), pointer :: ptr => null () end type build_target_ptr","tags":"","loc":"type/build_target_ptr.html"},{"title":"build_target_t – Fortran-lang/fpm ","text":"type, public :: build_target_t Type describing a generated build target Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: compile_flags Compile flags for this build target type( build_target_ptr ), public, allocatable :: dependencies (:) Resolved build dependencies integer(kind=int64), public, allocatable :: digest_cached Previous source file hash type( fortran_features_t ), public :: features Language features character(len=:), public, allocatable :: link_flags Link flags for this build target type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public, allocatable :: link_objects (:) Objects needed to link this target type( string_t ), public, allocatable :: macros (:) List of macros character(len=:), public, allocatable :: output_dir File path of output directory character(len=:), public, allocatable :: output_file File path of build target object relative to cwd character(len=:), public, allocatable :: output_log_file File path of build log file relative to cwd character(len=:), public, allocatable :: output_name File path of build target object relative to output_dir character(len=:), public, allocatable :: package_name Name of parent package integer, public :: schedule = -1 Targets in the same schedule group are guaranteed to be independent logical, public :: skip = .false. Flag set if build target will be skipped (not built) logical, public :: sorted = .false. Flag set if build target is sorted for building type( srcfile_t ), public, allocatable :: source Primary source for this build target integer, public :: target_type = FPM_TARGET_UNKNOWN Target type logical, public :: touched = .false. Flag set when first visited to check for circular dependencies character(len=:), public, allocatable :: version Version number Type-Bound Procedures procedure, public :: is_executable_target private elemental function is_executable_target(target_ptr, scope) result(is_exe) Arguments Type Intent Optional Attributes Name class( build_target_t ), intent(in) :: target_ptr integer, intent(in) :: scope Return Value logical Source Code type build_target_t !> File path of build target object relative to cwd character (:), allocatable :: output_file !> File path of build target object relative to output_dir character (:), allocatable :: output_name !> File path of output directory character (:), allocatable :: output_dir !> File path of build log file relative to cwd character (:), allocatable :: output_log_file !> Name of parent package character (:), allocatable :: package_name !> Primary source for this build target type ( srcfile_t ), allocatable :: source !> Resolved build dependencies type ( build_target_ptr ), allocatable :: dependencies (:) !> Target type integer :: target_type = FPM_TARGET_UNKNOWN !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> Objects needed to link this target type ( string_t ), allocatable :: link_objects (:) !> Link flags for this build target character (:), allocatable :: link_flags !> Compile flags for this build target character (:), allocatable :: compile_flags !> Flag set when first visited to check for circular dependencies logical :: touched = . false . !> Flag set if build target is sorted for building logical :: sorted = . false . !> Flag set if build target will be skipped (not built) logical :: skip = . false . !> Language features type ( fortran_features_t ) :: features !> Targets in the same schedule group are guaranteed to be independent integer :: schedule = - 1 !> Previous source file hash integer ( int64 ), allocatable :: digest_cached !> List of macros type ( string_t ), allocatable :: macros (:) !> Version number character (:), allocatable :: version contains procedure :: is_executable_target end type build_target_t","tags":"","loc":"type/build_target_t.html"},{"title":"fpm_build_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_cmd_settings ) :: fpm_build_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_build_settings.html"},{"title":"fpm_clean_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_cmd_settings ) :: fpm_clean_settings Components Type Visibility Attributes Name Initial logical, public :: clean_all = .false. logical, public :: clean_skip = .false. logical, public :: registry_cache = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_clean_settings.html"},{"title":"fpm_cmd_settings – Fortran-lang/fpm ","text":"type, public, abstract :: fpm_cmd_settings Components Type Visibility Attributes Name Initial logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_cmd_settings.html"},{"title":"fpm_export_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_build_settings ) :: fpm_export_settings Settings for exporting model data Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: dump_dependencies character(len=:), public, allocatable :: dump_manifest character(len=:), public, allocatable :: dump_model character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_export_settings.html"},{"title":"fpm_install_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_build_settings ) :: fpm_install_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: bindir logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: includedir character(len=:), public, allocatable :: ldflag character(len=:), public, allocatable :: libdir logical, public :: list = .false. logical, public :: no_rebuild character(len=:), public, allocatable :: prefix character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_install_settings.html"},{"title":"fpm_new_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_cmd_settings ) :: fpm_new_settings Components Type Visibility Attributes Name Initial logical, public :: backfill = .true. character(len=:), public, allocatable :: name logical, public :: verbose = .true. logical, public :: with_bare = .false. logical, public :: with_example = .false. logical, public :: with_executable = .false. logical, public :: with_full = .false. logical, public :: with_lib = .true. logical, public :: with_test = .false. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_new_settings.html"},{"title":"fpm_publish_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_build_settings ) :: fpm_publish_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag logical, public :: is_dry_run = .false. character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: show_package_version = .false. logical, public :: show_upload_data = .false. character(len=:), public, allocatable :: token logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_publish_settings.html"},{"title":"fpm_run_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_build_settings ) :: fpm_run_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: args logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump logical, public :: example character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=ibug), public, allocatable :: name (:) character(len=:), public, allocatable :: profile logical, public :: prune = .true. character(len=:), public, allocatable :: runner character(len=:), public, allocatable :: runner_args logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Type-Bound Procedures procedure, public :: name_ID private function name_ID(cmd, name) Check name in list ID. return 0 if not found\nDefault: not found Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(in) :: cmd character(len=*), intent(in) :: name Return Value integer procedure, public :: runner_command private function runner_command(cmd) result(run_cmd) Build a full runner command (executable + command-line arguments)\nGet executable\nAppend command-line arguments Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(in) :: cmd Return Value character(len=:), allocatable","tags":"","loc":"type/fpm_run_settings.html"},{"title":"fpm_test_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_run_settings ) :: fpm_test_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: args logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump logical, public :: example character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=ibug), public, allocatable :: name (:) character(len=:), public, allocatable :: profile logical, public :: prune = .true. character(len=:), public, allocatable :: runner character(len=:), public, allocatable :: runner_args logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Type-Bound Procedures procedure, public :: name_ID private function name_ID(cmd, name) Check name in list ID. return 0 if not found\nDefault: not found Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(in) :: cmd character(len=*), intent(in) :: name Return Value integer procedure, public :: runner_command private function runner_command(cmd) result(run_cmd) Build a full runner command (executable + command-line arguments)\nGet executable\nAppend command-line arguments Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(in) :: cmd Return Value character(len=:), allocatable","tags":"","loc":"type/fpm_test_settings.html"},{"title":"fpm_update_settings – Fortran-lang/fpm ","text":"type, public, extends( fpm_cmd_settings ) :: fpm_update_settings Settings for interacting and updating with project dependencies Components Type Visibility Attributes Name Initial logical, public :: clean character(len=:), public, allocatable :: dump logical, public :: fetch_only character(len=ibug), public, allocatable :: name (:) logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir","tags":"","loc":"type/fpm_update_settings.html"},{"title":"downloader_t – Fortran-lang/fpm ","text":"type, public :: downloader_t This type could be entirely avoided but it is quite practical because it can be mocked for testing. Type-Bound Procedures procedure, public, nopass :: get_file private subroutine get_file(url, tmp_pkg_file, error) Download a file from a url using either curl or wget. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url character(len=*), intent(in) :: tmp_pkg_file type( error_t ), intent(out), allocatable :: error procedure, public, nopass :: get_pkg_data private subroutine get_pkg_data(url, version, tmp_pkg_file, json, error) Perform an http get request, save output to file, and parse json. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url type( version_t ), intent(in), allocatable :: version character(len=*), intent(in) :: tmp_pkg_file type(json_object), intent(out) :: json type( error_t ), intent(out), allocatable :: error procedure, public, nopass :: unpack private subroutine unpack(tmp_pkg_file, destination, error) Unpack a tarball to a destination. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: tmp_pkg_file Path to tarball. character(len=*), intent(in) :: destination Destination to unpack to. type( error_t ), intent(out), allocatable :: error Error handling. procedure, public, nopass :: upload_form private subroutine upload_form(endpoint, form_data, verbose, error) Perform an http post request with form data. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: endpoint Endpoint to upload to. type( string_t ), intent(in) :: form_data (:) Form data to upload. logical, intent(in) :: verbose Print additional information if true. type( error_t ), intent(out), allocatable :: error Error handling.","tags":"","loc":"type/downloader_t.html"},{"title":"dependency_node_t – Fortran-lang/fpm ","text":"type, public, extends( dependency_config_t ) :: dependency_node_t Dependency node in the projects dependency tree Components Type Visibility Attributes Name Initial logical, public :: cached = .false. Dependency was loaded from a cache logical, public :: done = .false. Dependency is handled type( git_target_t ), public, allocatable :: git Git descriptor character(len=:), public, allocatable :: name Name of the dependency character(len=:), public, allocatable :: namespace Namespace which the dependency belongs to.\nEnables multiple dependencies with the same name.\nRequired for dependencies that are obtained via the official registry. character(len=:), public, allocatable :: path Local target type( preprocess_config_t ), public, allocatable :: preprocess (:) Requested macros for the dependency character(len=:), public, allocatable :: proj_dir Installation prefix of this dependencies type( version_t ), public, allocatable :: requested_version The requested version of the dependency.\nThe latest version is used if not specified. character(len=:), public, allocatable :: revision Checked out revision of the version control system logical, public :: update = .false. Dependency should be updated type( version_t ), public, allocatable :: version Actual version of this dependency Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => node_dump_to_toml private subroutine node_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: get_from_registry Get dependency from the registry. private subroutine get_from_registry(self, target_dir, global_settings, error, downloader_) Get a dependency from the registry. Whether the dependency is fetched\nfrom a local, a custom remote or the official registry is determined\nby the global configuration settings. Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(in) :: self Instance of the dependency configuration. character(len=:), intent(out), allocatable :: target_dir The target directory of the dependency. type( fpm_global_settings ), intent(in) :: global_settings Global configuration settings. type( error_t ), intent(out), allocatable :: error Error handling. class( downloader_t ), intent(in), optional :: downloader_ Downloader instance. procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Call base object info Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(in) :: self Instance of the dependency configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => node_load_from_toml private subroutine node_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: register Update dependency from project manifest. private subroutine register(self, package, root, fetch, revision, error) Update dependency from project manifest Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self Instance of the dependency node type( package_config_t ), intent(in) :: package Package configuration data character(len=*), intent(in) :: root Root directory of the project logical, intent(in) :: fetch Project has been fetched character(len=*), intent(in), optional :: revision Git revision of the project type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: serializable_is_same => dependency_node_is_same Serialization interface private function dependency_node_is_same(this, that) Check that two dependency nodes are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( dependency_config_t ) :: dependency_node_t !> Actual version of this dependency type ( version_t ), allocatable :: version !> Installation prefix of this dependencies character ( len = :), allocatable :: proj_dir !> Checked out revision of the version control system character ( len = :), allocatable :: revision !> Dependency is handled logical :: done = . false . !> Dependency should be updated logical :: update = . false . !> Dependency was loaded from a cache logical :: cached = . false . contains !> Update dependency from project manifest. procedure :: register !> Get dependency from the registry. procedure :: get_from_registry procedure , private :: get_from_local_registry !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => dependency_node_is_same procedure :: dump_to_toml => node_dump_to_toml procedure :: load_from_toml => node_load_from_toml end type dependency_node_t","tags":"","loc":"type/dependency_node_t.html"},{"title":"dependency_tree_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: dependency_tree_t Respresentation of a projects dependencies The dependencies are stored in a simple array for now, this can be replaced\nwith a binary-search tree or a hash table in the future. Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: cache Cache file type( dependency_node_t ), public, allocatable :: dep (:) Flattend list of all dependencies character(len=:), public, allocatable :: dep_dir Installation prefix for dependencies integer, public :: ndep = 0 Number of currently registered dependencies integer, public :: unit = output_unit Unit for IO integer, public :: verbosity = 1 Verbosity of printout Type-Bound Procedures generic, public :: add => add_project, add_project_dependencies, add_dependencies, add_dependency, add_dependency_node Overload procedure to add new dependencies to the tree private subroutine add_project(self, package, error) Add project dependencies, each depth level after each other. We implement this algorithm in an interative rather than a recursive fashion\nas a choice of design. Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( package_config_t ), intent(in) :: package Project configuration to add type( error_t ), intent(out), allocatable :: error Error handling private recursive subroutine add_project_dependencies(self, package, root, main, error) Add a project and its dependencies to the dependency tree\nEnsure allocation fits Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( package_config_t ), intent(in) :: package Project configuration to add character(len=*), intent(in) :: root Current project root directory logical, intent(in) :: main Is the main project type( error_t ), intent(out), allocatable :: error Error handling private subroutine add_dependencies(self, dependency, error) Add a list of dependencies to the dependency tree\nEnsure allocation fits ndep Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( dependency_config_t ), intent(in) :: dependency (:) Dependency configuration to add type( error_t ), intent(out), allocatable :: error Error handling private subroutine add_dependency(self, dependency, error) Add a single dependency to the dependency tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( dependency_config_t ), intent(in) :: dependency Dependency configuration to add type( error_t ), intent(out), allocatable :: error Error handling private subroutine add_dependency_node(self, dependency, error) Add a single dependency node to the dependency tree\nDependency nodes contain additional information (version, git, revision)\nSafety: reallocate if necessary Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( dependency_node_t ), intent(in) :: dependency Dependency configuration to add type( error_t ), intent(out), allocatable :: error Error handling generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? generic, public :: dump_cache => dump_cache_to_file, dump_cache_to_unit, dump_cache_to_toml Writing of dependency tree private subroutine dump_cache_to_file(self, file, error) Write dependency tree to file Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_cache_to_unit(self, unit, error) Write dependency tree to file Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_cache_to_toml(self, table, error) Write dependency tree to TOML datastructure Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: dump_to_toml => tree_dump_to_toml private subroutine tree_dump_to_toml(self, table, error) Dump dependency to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: find => find_name Find a dependency in the tree private pure function find_name(self, name) result(pos) Find a dependency in the dependency tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(in) :: self Instance of the dependency tree character(len=*), intent(in) :: name Dependency configuration to add Return Value integer Index of the dependency procedure, public :: finished Depedendncy resolution finished private pure function finished(self) Check if we are done with the dependency resolution Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(in) :: self Instance of the dependency tree Return Value logical All dependencies are updated generic, public :: has => has_dependency True if entity can be found private pure function has_dependency(self, dependency) True if dependency is part of the tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(in) :: self Instance of the dependency tree class( dependency_node_t ), intent(in) :: dependency Dependency configuration to check Return Value logical generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format generic, public :: load_cache => load_cache_from_file, load_cache_from_unit, load_cache_from_toml Reading of dependency tree private subroutine load_cache_from_file(self, file, error) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_cache_from_unit(self, unit, error) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_cache_from_toml(self, table, error) Read dependency tree from TOML data structure Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: load_from_toml => tree_load_from_toml private subroutine tree_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical generic, public :: resolve => resolve_dependencies, resolve_dependency Resolve dependencies private subroutine resolve_dependencies(self, root, error) Resolve all dependencies in the tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: root Current installation prefix type( error_t ), intent(out), allocatable :: error Error handling private subroutine resolve_dependency(self, dependency, global_settings, root, error) Resolve a single dependency node Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( dependency_node_t ), intent(inout) :: dependency Dependency configuration to add type( fpm_global_settings ), intent(in) :: global_settings Global configuration settings. character(len=*), intent(in) :: root Current installation prefix type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: serializable_is_same => dependency_tree_is_same Serialization interface private function dependency_tree_is_same(this, that) Check that two dependency trees are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error generic, public :: update => update_dependency, update_tree Update dependency tree private subroutine update_dependency(self, name, error) Update dependency tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: name Name of the dependency to update type( error_t ), intent(out), allocatable :: error Error handling private subroutine update_tree(self, error) Update whole dependency tree Arguments Type Intent Optional Attributes Name class( dependency_tree_t ), intent(inout) :: self Instance of the dependency tree type( error_t ), intent(out), allocatable :: error Error handling Source Code type , extends ( serializable_t ) :: dependency_tree_t !> Unit for IO integer :: unit = output_unit !> Verbosity of printout integer :: verbosity = 1 !> Installation prefix for dependencies character ( len = :), allocatable :: dep_dir !> Number of currently registered dependencies integer :: ndep = 0 !> Flattend list of all dependencies type ( dependency_node_t ), allocatable :: dep (:) !> Cache file character ( len = :), allocatable :: cache contains !> Overload procedure to add new dependencies to the tree generic :: add => add_project , add_project_dependencies , add_dependencies , & add_dependency , add_dependency_node !> Main entry point to add a project procedure , private :: add_project !> Add a project and its dependencies to the dependency tree procedure , private :: add_project_dependencies !> Add a list of dependencies to the dependency tree procedure , private :: add_dependencies !> Add a single dependency to the dependency tree procedure , private :: add_dependency !> Add a single dependency node to the dependency tree procedure , private :: add_dependency_node !> Resolve dependencies generic :: resolve => resolve_dependencies , resolve_dependency !> Resolve dependencies procedure , private :: resolve_dependencies !> Resolve dependency procedure , private :: resolve_dependency !> True if entity can be found generic :: has => has_dependency !> True if dependency is part of the tree procedure , private :: has_dependency !> Find a dependency in the tree generic :: find => find_name !> Find a dependency by its name procedure , private :: find_name !> Depedendncy resolution finished procedure :: finished !> Reading of dependency tree generic :: load_cache => load_cache_from_file , load_cache_from_unit , load_cache_from_toml !> Read dependency tree from file procedure , private :: load_cache_from_file !> Read dependency tree from formatted unit procedure , private :: load_cache_from_unit !> Read dependency tree from TOML data structure procedure , private :: load_cache_from_toml !> Writing of dependency tree generic :: dump_cache => dump_cache_to_file , dump_cache_to_unit , dump_cache_to_toml !> Write dependency tree to file procedure , private :: dump_cache_to_file !> Write dependency tree to formatted unit procedure , private :: dump_cache_to_unit !> Write dependency tree to TOML data structure procedure , private :: dump_cache_to_toml !> Update dependency tree generic :: update => update_dependency , update_tree !> Update a list of dependencies procedure , private :: update_dependency !> Update all dependencies in the tree procedure , private :: update_tree !> Serialization interface procedure :: serializable_is_same => dependency_tree_is_same procedure :: dump_to_toml => tree_dump_to_toml procedure :: load_from_toml => tree_load_from_toml end type dependency_tree_t","tags":"","loc":"type/dependency_tree_t.html"},{"title":"preprocess_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: preprocess_config_t Configuration meta data for a preprocessor Components Type Visibility Attributes Name Initial type( string_t ), public, allocatable :: directories (:) Directories to search for files to be preprocessed type( string_t ), public, allocatable :: macros (:) Macros to be defined for the preprocessor character(len=:), public, allocatable :: name Name of the preprocessor type( string_t ), public, allocatable :: suffixes (:) Suffixes of the files to be preprocessed Type-Bound Procedures procedure, public :: add_config private subroutine add_config(this, that) Add preprocessor settings Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(inout) :: this type( preprocess_config_t ), intent(in) :: that procedure, public :: destroy Operations private elemental subroutine destroy(this) Clean preprocessor structure Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(inout) :: this generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on this instance Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(in) :: self Instance of the preprocess configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout procedure, public :: is_cpp Properties private function is_cpp(this) Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(in) :: this Return Value logical procedure, public :: is_fypp private function is_fypp(this) Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(in) :: this Return Value logical generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => preprocess_is_same Serialization interface private function preprocess_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( preprocess_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: preprocess_config_t !> Name of the preprocessor character ( len = :), allocatable :: name !> Suffixes of the files to be preprocessed type ( string_t ), allocatable :: suffixes (:) !> Directories to search for files to be preprocessed type ( string_t ), allocatable :: directories (:) !> Macros to be defined for the preprocessor type ( string_t ), allocatable :: macros (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => preprocess_is_same procedure :: dump_to_toml procedure :: load_from_toml !> Operations procedure :: destroy procedure :: add_config !> Properties procedure :: is_cpp procedure :: is_fypp end type preprocess_config_t","tags":"","loc":"type/preprocess_config_t.html"},{"title":"fortran_features_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: fortran_features_t Enabled Fortran language features Components Type Visibility Attributes Name Initial logical, public :: implicit_external = .false. Use implicit external interface logical, public :: implicit_typing = .false. Use default implicit typing character(len=:), public, allocatable :: source_form Form to use for all Fortran sources Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => fft_dump_to_toml private subroutine fft_dump_to_toml(self, table, error) Dump fortran features to toml table Arguments Type Intent Optional Attributes Name class( fortran_features_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => fft_load_from_toml private subroutine fft_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( fortran_features_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => fft_is_same Serialization interface private function fft_is_same(this, that) Check that two fortran feature objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( fortran_features_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: fortran_features_t !> Use default implicit typing logical :: implicit_typing = . false . !> Use implicit external interface logical :: implicit_external = . false . !> Form to use for all Fortran sources character (:), allocatable :: source_form contains !> Serialization interface procedure :: serializable_is_same => fft_is_same procedure :: dump_to_toml => fft_dump_to_toml procedure :: load_from_toml => fft_load_from_toml end type fortran_features_t","tags":"","loc":"type/fortran_features_t.html"},{"title":"fpm_model_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: fpm_model_t Type describing everything required to build\n the root package and its dependencies. Components Type Visibility Attributes Name Initial type( archiver_t ), public :: archiver Archiver object character(len=:), public, allocatable :: build_prefix Base directory for build character(len=:), public, allocatable :: c_compile_flags Command line flags passed to C for compilation type( compiler_t ), public :: compiler Compiler object character(len=:), public, allocatable :: cxx_compile_flags Command line flags passed to C++ for compilation type( dependency_tree_t ), public :: deps Project dependencies logical, public :: enforce_module_names = .false. Whether module names should be prefixed with the package name type( string_t ), public, allocatable :: external_modules (:) External modules used character(len=:), public, allocatable :: fortran_compile_flags Command line flags passed to fortran for compilation type( string_t ), public, allocatable :: include_dirs (:) Include directories logical, public :: include_tests = .true. Whether tests should be added to the build list character(len=:), public, allocatable :: link_flags Command line flags passed to the linker type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public :: module_prefix Prefix for all module names character(len=:), public, allocatable :: package_name Name of root package type( package_t ), public, allocatable :: packages (:) Array of packages (including the root package) Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => model_dump_to_toml private subroutine model_dump_to_toml(self, table, error) Dump dependency to toml table Array of packages (including the root package) Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( fpm_model_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => model_load_from_toml private subroutine model_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Read all packages Arguments Type Intent Optional Attributes Name class( fpm_model_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => model_is_same Serialization interface private function model_is_same(this, that) Check that two model objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( fpm_model_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: fpm_model_t !> Name of root package character (:), allocatable :: package_name !> Array of packages (including the root package) type ( package_t ), allocatable :: packages (:) !> Compiler object type ( compiler_t ) :: compiler !> Archiver object type ( archiver_t ) :: archiver !> Command line flags passed to fortran for compilation character (:), allocatable :: fortran_compile_flags !> Command line flags passed to C for compilation character (:), allocatable :: c_compile_flags !> Command line flags passed to C++ for compilation character (:), allocatable :: cxx_compile_flags !> Command line flags passed to the linker character (:), allocatable :: link_flags !> Base directory for build character (:), allocatable :: build_prefix !> Include directories type ( string_t ), allocatable :: include_dirs (:) !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> External modules used type ( string_t ), allocatable :: external_modules (:) !> Project dependencies type ( dependency_tree_t ) :: deps !> Whether tests should be added to the build list logical :: include_tests = . true . !> Whether module names should be prefixed with the package name logical :: enforce_module_names = . false . !> Prefix for all module names type ( string_t ) :: module_prefix contains !> Serialization interface procedure :: serializable_is_same => model_is_same procedure :: dump_to_toml => model_dump_to_toml procedure :: load_from_toml => model_load_from_toml end type fpm_model_t","tags":"","loc":"type/fpm_model_t.html"},{"title":"package_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: package_t Type for describing a single package Components Type Visibility Attributes Name Initial logical, public :: enforce_module_names = .false. Module naming conventions type( fortran_features_t ), public :: features Language features type( string_t ), public :: module_prefix Prefix for all module names character(len=:), public, allocatable :: name Name of package type( preprocess_config_t ), public :: preprocess List of macros. type( srcfile_t ), public, allocatable :: sources (:) Array of sources character(len=:), public, allocatable :: version Package version number. Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => package_dump_to_toml private subroutine package_dump_to_toml(self, table, error) Dump dependency to toml table Create a preprocessor table\nCreate a fortran table\nCreate a sources table Arguments Type Intent Optional Attributes Name class( package_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => package_load_from_toml private subroutine package_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( package_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => package_is_same Serialization interface private function package_is_same(this, that) Check that two package objects are equal\nModule naming\nFortran features All checks passed! Arguments Type Intent Optional Attributes Name class( package_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: package_t !> Name of package character (:), allocatable :: name !> Array of sources type ( srcfile_t ), allocatable :: sources (:) !> List of macros. type ( preprocess_config_t ) :: preprocess !> Package version number. character (:), allocatable :: version !> Module naming conventions logical :: enforce_module_names = . false . !> Prefix for all module names type ( string_t ) :: module_prefix !> Language features type ( fortran_features_t ) :: features contains !> Serialization interface procedure :: serializable_is_same => package_is_same procedure :: dump_to_toml => package_dump_to_toml procedure :: load_from_toml => package_load_from_toml end type package_t","tags":"","loc":"type/package_t.html"},{"title":"srcfile_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: srcfile_t Type for describing a source file Components Type Visibility Attributes Name Initial integer(kind=int64), public :: digest Current hash character(len=:), public, allocatable :: exe_name Name of executable for FPM_UNIT_PROGRAM character(len=:), public, allocatable :: file_name File path relative to cwd type( string_t ), public, allocatable :: include_dependencies (:) Files INCLUDEd by this source file type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public, allocatable :: modules_provided (:) Modules provided by this source file (lowerstring) type( string_t ), public, allocatable :: modules_used (:) Modules USEd by this source file (lowerstring) type( string_t ), public, allocatable :: parent_modules (:) Parent modules (submodules only) integer, public :: unit_scope = FPM_SCOPE_UNKNOWN Target module-use scope integer, public :: unit_type = FPM_UNIT_UNKNOWN Type of source unit Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => srcfile_dump_to_toml private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => srcfile_load_from_toml private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => srcfile_is_same Serialization interface private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: srcfile_t !> File path relative to cwd character (:), allocatable :: file_name !> Name of executable for FPM_UNIT_PROGRAM character (:), allocatable :: exe_name !> Target module-use scope integer :: unit_scope = FPM_SCOPE_UNKNOWN !> Modules provided by this source file (lowerstring) type ( string_t ), allocatable :: modules_provided (:) !> Type of source unit integer :: unit_type = FPM_UNIT_UNKNOWN !> Parent modules (submodules only) type ( string_t ), allocatable :: parent_modules (:) !> Modules USEd by this source file (lowerstring) type ( string_t ), allocatable :: modules_used (:) !> Files INCLUDEd by this source file type ( string_t ), allocatable :: include_dependencies (:) !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> Current hash integer ( int64 ) :: digest contains !> Serialization interface procedure :: serializable_is_same => srcfile_is_same procedure :: dump_to_toml => srcfile_dump_to_toml procedure :: load_from_toml => srcfile_load_from_toml end type srcfile_t","tags":"","loc":"type/srcfile_t.html"},{"title":"console_t – Fortran-lang/fpm ","text":"type, public :: console_t Console object Components Type Visibility Attributes Name Initial integer, public :: n_line = 1 Number of lines printed Type-Bound Procedures procedure, public :: update_line => console_update_line Update a previously-written console line private subroutine console_update_line(console, line_no, str) Overwrite a previously-written line in standard output Arguments Type Intent Optional Attributes Name class( console_t ), intent(in) :: console Console object integer, intent(in) :: line_no Integer output from [[console_write_line]] character(len=*), intent(in) :: str New string to overwrite line procedure, public :: write_line => console_write_line Write a single line to the console private subroutine console_write_line(console, str, line, advance) Write a single line to the standard output Arguments Type Intent Optional Attributes Name class( console_t ), intent(inout) :: console Console object character(len=*), intent(in) :: str String to write integer, intent(out), optional :: line Integer needed to later update console line logical, intent(in), optional :: advance Advancing output (print newline?) Source Code type console_t !> Number of lines printed integer :: n_line = 1 contains !> Write a single line to the console procedure :: write_line => console_write_line !> Update a previously-written console line procedure :: update_line => console_update_line end type console_t","tags":"","loc":"type/console_t.html"},{"title":"metapackage_config_t – Fortran-lang/fpm ","text":"type, public :: metapackage_config_t Configuration data for metapackages Components Type Visibility Attributes Name Initial type( metapackage_request_t ), public :: hdf5 HDF5 type( metapackage_request_t ), public :: minpack fortran-lang minpack type( metapackage_request_t ), public :: mpi Request MPI support type( metapackage_request_t ), public :: openmp Request OpenMP support type( metapackage_request_t ), public :: stdlib Request stdlib support Source Code type :: metapackage_config_t !> Request MPI support type ( metapackage_request_t ) :: mpi !> Request OpenMP support type ( metapackage_request_t ) :: openmp !> Request stdlib support type ( metapackage_request_t ) :: stdlib !> fortran-lang minpack type ( metapackage_request_t ) :: minpack !> HDF5 type ( metapackage_request_t ) :: hdf5 end type metapackage_config_t","tags":"","loc":"type/metapackage_config_t.html"},{"title":"metapackage_request_t – Fortran-lang/fpm ","text":"type, public :: metapackage_request_t Configuration data for a single metapackage request Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: name Metapackage name logical, public :: on = .false. Request flag character(len=:), public, allocatable :: version Version Specification string Source Code type :: metapackage_request_t !> Request flag logical :: on = . false . !> Metapackage name character ( len = :), allocatable :: name !> Version Specification string character ( len = :), allocatable :: version end type metapackage_request_t","tags":"","loc":"type/metapackage_request_t.html"},{"title":"example_config_t – Fortran-lang/fpm ","text":"type, public, extends( executable_config_t ) :: example_config_t Configuation meta data for an example Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( example_config_t ), intent(in) :: self Instance of the example configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => exe_is_same Serialization interface private function exe_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( executable_config_t ) :: example_config_t contains !> Print information on this instance procedure :: info end type example_config_t","tags":"","loc":"type/example_config_t.html"},{"title":"executable_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: executable_config_t Configuation meta data for an executable Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(in) :: self Instance of the executable configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => exe_is_same Serialization interface private function exe_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: executable_config_t !> Name of the resulting executable character ( len = :), allocatable :: name !> Source directory for collecting the executable character ( len = :), allocatable :: source_dir !> Name of the source file declaring the main program character ( len = :), allocatable :: main !> Dependency meta data for this executable type ( dependency_config_t ), allocatable :: dependency (:) !> Libraries to link against type ( string_t ), allocatable :: link (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => exe_is_same procedure :: dump_to_toml procedure :: load_from_toml end type executable_config_t","tags":"","loc":"type/executable_config_t.html"},{"title":"fpm_global_settings – Fortran-lang/fpm ","text":"type, public :: fpm_global_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: config_file_name Name of the global config file. The default is config.toml . character(len=:), public, allocatable :: path_to_config_folder Path to the global config file excluding the file name. type(fpm_registry_settings), public, allocatable :: registry_settings Registry configs. Type-Bound Procedures procedure, public :: full_path private function full_path(self) result(result) The full path to the global config file. Arguments Type Intent Optional Attributes Name class( fpm_global_settings ), intent(in) :: self Return Value character(len=:), allocatable procedure, public :: has_custom_location private elemental function has_custom_location(self) True if the global config file is not at the default location. Arguments Type Intent Optional Attributes Name class( fpm_global_settings ), intent(in) :: self Return Value logical procedure, public :: path_to_config_folder_or_empty private pure function path_to_config_folder_or_empty(self) The path to the global config directory. Arguments Type Intent Optional Attributes Name class( fpm_global_settings ), intent(in) :: self Return Value character(len=:), allocatable","tags":"","loc":"type/fpm_global_settings.html"},{"title":"library_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: library_config_t Configuration meta data for a library Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: build_script Alternative build script to be invoked type( string_t ), public, allocatable :: include_dir (:) Include path prefix character(len=:), public, allocatable :: source_dir Source path prefix Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Arguments Type Intent Optional Attributes Name class( library_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( library_config_t ), intent(in) :: self Instance of the library configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( library_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => library_is_same Serialization interface private function library_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( library_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: library_config_t !> Source path prefix character ( len = :), allocatable :: source_dir !> Include path prefix type ( string_t ), allocatable :: include_dir (:) !> Alternative build script to be invoked character ( len = :), allocatable :: build_script contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => library_is_same procedure :: dump_to_toml procedure :: load_from_toml end type library_config_t","tags":"","loc":"type/library_config_t.html"},{"title":"archiver_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: archiver_t Definition of archiver object Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: ar Path to archiver logical, public :: echo = .true. Print all command logical, public :: use_response_file = .false. Use response files to pass arguments logical, public :: verbose = .true. Verbose output of command Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml public subroutine dump_to_toml (self, table, error) Dump dependency to toml table Read more… Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml public subroutine load_from_toml (self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: make_archive Create static archive public subroutine make_archive (self, output, args, log_file, stat) Create an archive Read more… Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: self Instance of the archiver object character(len=*), intent(in) :: output Name of the archive to generate type( string_t ), intent(in) :: args (:) Object files to include into the archive character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => ar_is_same Serialization interface public function ar_is_same (this, that) Check that two archiver_t objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: archiver_t !> Path to archiver character ( len = :), allocatable :: ar !> Use response files to pass arguments logical :: use_response_file = . false . !> Print all command logical :: echo = . true . !> Verbose output of command logical :: verbose = . true . contains !> Create static archive procedure :: make_archive !> Serialization interface procedure :: serializable_is_same => ar_is_same procedure :: dump_to_toml procedure :: load_from_toml end type archiver_t","tags":"","loc":"type/archiver_t.html"},{"title":"compiler_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: compiler_t Definition of compiler object Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: cc Path to the C compiler character(len=:), public, allocatable :: cxx Path to the C++ compiler logical, public :: echo = .true. Print all commands character(len=:), public, allocatable :: fc Path to the Fortran compiler integer(kind=compiler_enum), public :: id = id_unknown Identifier of the compiler logical, public :: verbose = .true. Verbose output of command Type-Bound Procedures procedure, public :: check_fortran_source_runs Fortran feature support public function check_fortran_source_runs (self, input) result(success) Run a single-source Fortran program using the current compiler\nCompile a Fortran object\nCreate temporary source file\nWrite contents\nCompile and link program\nRun and retrieve exit code Read more… Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Program Source Return Value logical procedure, public :: compile_c Compile a C object public subroutine compile_c (self, input, output, args, log_file, stat) Compile a C object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag procedure, public :: compile_cpp Compile a CPP object public subroutine compile_cpp (self, input, output, args, log_file, stat) Compile a CPP object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag procedure, public :: compile_fortran Compile a Fortran object public subroutine compile_fortran (self, input, output, args, log_file, stat) Compile a Fortran object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml => compiler_dump public subroutine compiler_dump (self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: enumerate_libraries Enumerate libraries, based on compiler and platform public function enumerate_libraries (self, prefix, libs) result(r) Enumerate libraries, based on compiler and platform Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: prefix type( string_t ), intent(in) :: libs (:) Return Value character(len=:), allocatable procedure, public :: get_default_flags Get default compiler flags public function get_default_flags (self, release) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self logical, intent(in) :: release Return Value character(len=:), allocatable procedure, public :: get_feature_flag Get feature flag public function get_feature_flag (self, feature) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: feature Return Value character(len=:), allocatable procedure, public :: get_include_flag Get flag for include directories public function get_include_flag (self, path) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable procedure, public :: get_main_flags Get flags for the main linking command public subroutine get_main_flags (self, language, flags) Get special flags for the main linker Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: language character(len=:), intent(out), allocatable :: flags procedure, public :: get_module_flag Get flag for module output directories public function get_module_flag (self, path) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable procedure, public :: is_gnu Check whether this is a GNU compiler public pure function is_gnu (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical procedure, public :: is_intel Check whether this is an Intel compiler public pure function is_intel (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical procedure, public :: is_unknown Check whether compiler is recognized public pure function is_unknown (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical procedure, public :: link Link executable public subroutine link (self, output, args, log_file, stat) Link an executable Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml => compiler_load public subroutine compiler_load (self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: name => compiler_name Return compiler name public pure function compiler_name (self) result(name) Return a compiler name string Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => compiler_is_same Serialization interface public function compiler_is_same (this, that) Check that two compiler_t objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error procedure, public :: with_qp public function with_qp (self) Check if the current compiler supports 128-bit real precision Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical procedure, public :: with_xdp public function with_xdp (self) Check if the current compiler supports 80-bit “extended” real precision Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical Source Code type , extends ( serializable_t ) :: compiler_t !> Identifier of the compiler integer ( compiler_enum ) :: id = id_unknown !> Path to the Fortran compiler character ( len = :), allocatable :: fc !> Path to the C compiler character ( len = :), allocatable :: cc !> Path to the C++ compiler character ( len = :), allocatable :: cxx !> Print all commands logical :: echo = . true . !> Verbose output of command logical :: verbose = . true . contains !> Get default compiler flags procedure :: get_default_flags !> Get flag for module output directories procedure :: get_module_flag !> Get flag for include directories procedure :: get_include_flag !> Get feature flag procedure :: get_feature_flag !> Get flags for the main linking command procedure :: get_main_flags !> Compile a Fortran object procedure :: compile_fortran !> Compile a C object procedure :: compile_c !> Compile a CPP object procedure :: compile_cpp !> Link executable procedure :: link !> Check whether compiler is recognized procedure :: is_unknown !> Check whether this is an Intel compiler procedure :: is_intel !> Check whether this is a GNU compiler procedure :: is_gnu !> Enumerate libraries, based on compiler and platform procedure :: enumerate_libraries !> Serialization interface procedure :: serializable_is_same => compiler_is_same procedure :: dump_to_toml => compiler_dump procedure :: load_from_toml => compiler_load !> Fortran feature support procedure :: check_fortran_source_runs procedure :: with_xdp procedure :: with_qp !> Return compiler name procedure :: name => compiler_name end type compiler_t","tags":"","loc":"type/compiler_t.html"},{"title":"error_t – Fortran-lang/fpm ","text":"type, public :: error_t Data type defining an error Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: message Error message Source Code type :: error_t !> Error message character ( len = :), allocatable :: message end type error_t","tags":"","loc":"type/error_t.html"},{"title":"test_config_t – Fortran-lang/fpm ","text":"type, public, extends( executable_config_t ) :: test_config_t Configuation meta data for an test Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Because dependencies are named, fallback if this has no name\nSo, serialization will work regardless of size(self%dep) == self%ndep Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling procedure, public :: info Print information on this instance private subroutine info(self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( test_config_t ), intent(in) :: self Instance of the test configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Read all dependencies Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => exe_is_same Serialization interface private function exe_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( executable_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( executable_config_t ) :: test_config_t contains !> Print information on this instance procedure :: info end type test_config_t","tags":"","loc":"type/test_config_t.html"},{"title":"metapackage_t – Fortran-lang/fpm ","text":"type, public :: metapackage_t Type for describing a source file Components Type Visibility Attributes Name Initial type( string_t ), public :: cflags type( string_t ), public :: cxxflags type( dependency_config_t ), public, allocatable :: dependency (:) List of Development dependency meta data.\nMetapackage dependencies are never exported from the model type( string_t ), public, allocatable :: external_modules (:) type( string_t ), public :: fflags type( string_t ), public :: flags List of compiler flags and options to be added type( fortran_features_t ), public, allocatable :: fortran Special fortran features logical, public :: has_build_flags = .false. logical, public :: has_c_flags = .false. logical, public :: has_cxx_flags = .false. logical, public :: has_dependencies = .false. logical, public :: has_external_modules = .false. logical, public :: has_fortran_flags = .false. logical, public :: has_include_dirs = .false. logical, public :: has_link_flags = .false. logical, public :: has_link_libraries = .false. logical, public :: has_run_command = .false. type( string_t ), public, allocatable :: incl_dirs (:) type( string_t ), public :: link_flags type( string_t ), public, allocatable :: link_libs (:) type( string_t ), public :: run_command type( version_t ), public, allocatable :: version Package version (if supported) Type-Bound Procedures procedure, public :: destroy Clean metapackage structure private elemental subroutine destroy(this) Clean the metapackage structure Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(inout) :: this procedure, public :: new => init_from_name Initialize the metapackage structure from its given name private subroutine init_from_name(this, name, compiler, error) Initialize a metapackage from the given name\nInitialize metapackage by name Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(inout) :: this character(len=*), intent(in) :: name type( compiler_t ), intent(in) :: compiler type( error_t ), intent(out), allocatable :: error generic, public :: resolve => resolve_cmd, resolve_model, resolve_package_config private subroutine resolve_cmd(self, settings, error) Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(in) :: self class( fpm_cmd_settings ), intent(inout) :: settings type( error_t ), intent(out), allocatable :: error private subroutine resolve_model(self, model, error) Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(in) :: self type( fpm_model_t ), intent(inout) :: model type( error_t ), intent(out), allocatable :: error private subroutine resolve_package_config(self, package, error) Arguments Type Intent Optional Attributes Name class( metapackage_t ), intent(in) :: self type( package_config_t ), intent(inout) :: package type( error_t ), intent(out), allocatable :: error Source Code type , public :: metapackage_t !> Package version (if supported) type ( version_t ), allocatable :: version logical :: has_link_libraries = . false . logical :: has_link_flags = . false . logical :: has_build_flags = . false . logical :: has_fortran_flags = . false . logical :: has_c_flags = . false . logical :: has_cxx_flags = . false . logical :: has_include_dirs = . false . logical :: has_dependencies = . false . logical :: has_run_command = . false . logical :: has_external_modules = . false . !> List of compiler flags and options to be added type ( string_t ) :: flags type ( string_t ) :: fflags type ( string_t ) :: cflags type ( string_t ) :: cxxflags type ( string_t ) :: link_flags type ( string_t ) :: run_command type ( string_t ), allocatable :: incl_dirs (:) type ( string_t ), allocatable :: link_libs (:) type ( string_t ), allocatable :: external_modules (:) !> Special fortran features type ( fortran_features_t ), allocatable :: fortran !> List of Development dependency meta data. !> Metapackage dependencies are never exported from the model type ( dependency_config_t ), allocatable :: dependency (:) contains !> Clean metapackage structure procedure :: destroy !> Initialize the metapackage structure from its given name procedure :: new => init_from_name !> Add metapackage dependencies to the model procedure , private :: resolve_cmd procedure , private :: resolve_model procedure , private :: resolve_package_config generic :: resolve => resolve_cmd , resolve_model , resolve_package_config end type metapackage_t","tags":"","loc":"type/metapackage_t.html"},{"title":"string_t – Fortran-lang/fpm ","text":"type, public :: string_t Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: s Constructor public interface string_t private function new_string_t(s) result(string) Helper function to generate a new string_t instance\n (Required due to the allocatable component) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s Return Value type( string_t )","tags":"","loc":"type/string_t.html"},{"title":"fortran_config_t – Fortran-lang/fpm ","text":"type, public, extends( serializable_t ) :: fortran_config_t Configuration data for Fortran Components Type Visibility Attributes Name Initial logical, public :: implicit_external = .false. Enable implicit external interfaces logical, public :: implicit_typing = .false. Enable default implicit typing character(len=:), public, allocatable :: source_form Form to use for all Fortran sources Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit private subroutine srcfile_dump_to_toml(self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine dump_to_file(self, file, error, json) Write serializable object to file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine dump_to_unit(self, unit, error, json) Write serializable object to a formatted Fortran unit Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit Formatted unit type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format requested? procedure, public :: dump_to_toml private subroutine dump_to_toml(self, table, error) Dump install config to toml table Arguments Type Intent Optional Attributes Name class( fortran_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: load => load_from_toml , load_from_file, load_from_unit private subroutine srcfile_load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling private subroutine load_from_file(self, file, error, json) Read dependency tree from file Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree character(len=*), intent(in) :: file File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format private subroutine load_from_unit(self, unit, error, json) Read dependency tree from file\ninit JSON interpreter\nRead object from TOML table use default TOML parser Read object from TOML table Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self Instance of the dependency tree integer, intent(in) :: unit File name type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in), optional :: json Optional JSON format procedure, public :: load_from_toml private subroutine load_from_toml(self, table, error) Read install config from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( fortran_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling generic, public :: operator(==) => serializable_is_same private function srcfile_is_same(this, that) Check that two source files are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( srcfile_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public :: serializable_is_same => fortran_is_same Serialization interface private function fortran_is_same(this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( fortran_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical procedure, public, non_overridable :: test_serialization Test load/write roundtrip private subroutine test_serialization(self, message, error) Test serialization of a serializable object\nDump to scratch file\nLoad from scratch file\nCheck same Arguments Type Intent Optional Attributes Name class( serializable_t ), intent(inout) :: self character(len=*), intent(in) :: message type( error_t ), intent(out), allocatable :: error Source Code type , extends ( serializable_t ) :: fortran_config_t !> Enable default implicit typing logical :: implicit_typing = . false . !> Enable implicit external interfaces logical :: implicit_external = . false . !> Form to use for all Fortran sources character (:), allocatable :: source_form contains !> Serialization interface procedure :: serializable_is_same => fortran_is_same procedure :: dump_to_toml procedure :: load_from_toml end type fortran_config_t","tags":"","loc":"type/fortran_config_t.html"},{"title":"new_build_config – Fortran-lang/fpm","text":"public subroutine new_build_config(self, table, package_name, error) Construct a new build configuration from a TOML data structure Module naming: fist, attempt boolean value first Value found, but not a boolean. Attempt to read a prefix string Arguments Type Intent Optional Attributes Name type( build_config_t ), intent(out) :: self Instance of the build configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: package_name Package name type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_build_config ( self , table , package_name , error ) !> Instance of the build configuration type ( build_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Package name character ( len =* ), intent ( in ) :: package_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat call check ( table , package_name , error ) if ( allocated ( error )) return call get_value ( table , \"auto-executables\" , self % auto_executables , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-executables' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"auto-tests\" , self % auto_tests , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-tests' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"auto-examples\" , self % auto_examples , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-examples' in fpm.toml, expecting logical\" ) return end if !> Module naming: fist, attempt boolean value first call get_value ( table , \"module-naming\" , self % module_naming , . false ., stat = stat ) if ( stat == toml_stat % success ) then ! Boolean value found. Set no custom prefix. This also falls back to key not provided if ( allocated ( self % module_prefix % s )) deallocate ( self % module_prefix % s ) else !> Value found, but not a boolean. Attempt to read a prefix string call get_value ( table , \"module-naming\" , self % module_prefix % s ) if (. not . allocated ( self % module_prefix % s )) then call syntax_error ( error , \"Could not read value for 'module-naming' in fpm.toml, expecting logical or a string\" ) return end if if (. not . is_valid_module_prefix ( self % module_prefix )) then call syntax_error ( error , \"Invalid custom module name prefix for in fpm.toml: <\" // self % module_prefix % s // & \">, expecting a valid alphanumeric string\" ) return end if ! Set module naming to ON self % module_naming = . true . end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return call get_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return end subroutine new_build_config","tags":"","loc":"proc/new_build_config.html"},{"title":"new_install_config – Fortran-lang/fpm","text":"public subroutine new_install_config(self, table, error) Create a new installation configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( install_config_t ), intent(out) :: self Instance of the install configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_install_config ( self , table , error ) !> Instance of the install configuration type ( install_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"library\" , self % library , . false .) end subroutine new_install_config","tags":"","loc":"proc/new_install_config.html"},{"title":"manifest_has_changed – Fortran-lang/fpm","text":"public function manifest_has_changed(cached, manifest, verbosity, iunit) result(has_changed) Check if two dependency configurations are different Perform all checks\nAll checks passed! The two instances are equal Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(in) :: cached Two instances of the dependency configuration class( dependency_config_t ), intent(in) :: manifest Two instances of the dependency configuration integer, intent(in) :: verbosity Log verbosity integer, intent(in) :: iunit Log verbosity Return Value logical Source Code logical function manifest_has_changed ( cached , manifest , verbosity , iunit ) result ( has_changed ) !> Two instances of the dependency configuration class ( dependency_config_t ), intent ( in ) :: cached , manifest !> Log verbosity integer , intent ( in ) :: verbosity , iunit has_changed = . true . !> Perform all checks if ( allocated ( cached % git ). neqv . allocated ( manifest % git )) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT presence has changed. \" return endif if ( allocated ( cached % git )) then if (. not . git_matches_manifest ( cached % git , manifest % git , verbosity , iunit )) return end if !> All checks passed! The two instances are equal has_changed = . false . end function manifest_has_changed","tags":"","loc":"proc/manifest_has_changed.html"},{"title":"dependency_destroy – Fortran-lang/fpm","text":"public elemental subroutine dependency_destroy(self) Clean memory Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(inout) :: self Source Code elemental subroutine dependency_destroy ( self ) class ( dependency_config_t ), intent ( inout ) :: self if ( allocated ( self % name )) deallocate ( self % name ) if ( allocated ( self % path )) deallocate ( self % path ) if ( allocated ( self % namespace )) deallocate ( self % namespace ) if ( allocated ( self % requested_version )) deallocate ( self % requested_version ) if ( allocated ( self % git )) deallocate ( self % git ) end subroutine dependency_destroy","tags":"","loc":"proc/dependency_destroy.html"},{"title":"new_dependencies – Fortran-lang/fpm","text":"public subroutine new_dependencies(deps, table, root, meta, error) Construct new dependency array from a TOML data structure Flag dependencies that should be treated as metapackages\nParse all meta- and non-metapackage dependencies Neither a standard dep nor a metapackage\nValid meta dependency Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(out), allocatable :: deps (:) Instance of the dependency configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( metapackage_config_t ), intent(out), optional :: meta (optional) metapackages type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_dependencies ( deps , table , root , meta , error ) !> Instance of the dependency configuration type ( dependency_config_t ), allocatable , intent ( out ) :: deps (:) !> (optional) metapackages type ( metapackage_config_t ), optional , intent ( out ) :: meta !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( * ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: node type ( toml_key ), allocatable :: list (:) type ( dependency_config_t ), allocatable :: all_deps (:) type ( metapackage_request_t ) :: meta_request logical , allocatable :: is_meta (:) logical :: metapackages_allowed integer :: idep , stat , ndep call table % get_keys ( list ) ! An empty table is okay if ( size ( list ) < 1 ) return !> Flag dependencies that should be treated as metapackages metapackages_allowed = present ( meta ) allocate ( is_meta ( size ( list )), source = . false .) allocate ( all_deps ( size ( list ))) !> Parse all meta- and non-metapackage dependencies do idep = 1 , size ( list ) ! Check if this is a standard dependency node call get_value ( table , list ( idep )% key , node , stat = stat ) is_standard_dependency : if ( stat /= toml_stat % success ) then ! See if it can be a valid metapackage name call new_meta_request ( meta_request , list ( idep )% key , table , error = error ) !> Neither a standard dep nor a metapackage if ( allocated ( error )) then call syntax_error ( error , \"Dependency \" // list ( idep )% key // \" is not a valid metapackage or a table entry\" ) return endif !> Valid meta dependency is_meta ( idep ) = . true . else ! Parse as a standard dependency is_meta ( idep ) = . false . call new_dependency ( all_deps ( idep ), node , root , error ) if ( allocated ( error )) return end if is_standard_dependency end do ! Non-meta dependencies ndep = count (. not . is_meta ) ! Finalize standard dependencies allocate ( deps ( ndep )) ndep = 0 do idep = 1 , size ( list ) if ( is_meta ( idep )) cycle ndep = ndep + 1 deps ( ndep ) = all_deps ( idep ) end do ! Finalize meta dependencies if ( metapackages_allowed ) call new_meta_config ( meta , table , is_meta , error ) end subroutine new_dependencies","tags":"","loc":"proc/new_dependencies.html"},{"title":"new_dependency – Fortran-lang/fpm","text":"public subroutine new_dependency(self, table, root, error) Construct a new dependency configuration from a TOML data structure Get optional preprocessor directives Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(out) :: self Instance of the dependency configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_dependency ( self , table , root , error ) !> Instance of the dependency configuration type ( dependency_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( * ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: uri , value , requested_version type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call table % get_key ( self % name ) call get_value ( table , \"namespace\" , self % namespace ) call get_value ( table , \"v\" , requested_version ) if ( allocated ( requested_version )) then if (. not . allocated ( self % requested_version )) allocate ( self % requested_version ) call new_version ( self % requested_version , requested_version , error ) if ( allocated ( error )) return end if !> Get optional preprocessor directives call get_value ( table , \"preprocess\" , child , requested = . false .) if ( associated ( child )) then call new_preprocessors ( self % preprocess , child , error ) if ( allocated ( error )) return endif call get_value ( table , \"path\" , uri ) if ( allocated ( uri )) then if ( get_os_type () == OS_WINDOWS ) uri = windows_path ( uri ) if ( present ( root )) uri = join_path ( root , uri ) ! Relative to the fpm.toml it’s written in call move_alloc ( uri , self % path ) return end if call get_value ( table , \"git\" , uri ) if ( allocated ( uri )) then call get_value ( table , \"tag\" , value ) if ( allocated ( value )) then self % git = git_target_tag ( uri , value ) end if if (. not . allocated ( self % git )) then call get_value ( table , \"branch\" , value ) if ( allocated ( value )) then self % git = git_target_branch ( uri , value ) end if end if if (. not . allocated ( self % git )) then call get_value ( table , \"rev\" , value ) if ( allocated ( value )) then self % git = git_target_revision ( uri , value ) end if end if if (. not . allocated ( self % git )) then self % git = git_target_default ( uri ) end if return end if end subroutine new_dependency","tags":"","loc":"proc/new_dependency.html"},{"title":"resize – Fortran-lang/fpm","text":"public interface resize Module Procedures private pure subroutine resize_dependency_config(var, n) Reallocate a list of dependencies Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(inout), allocatable :: var (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size","tags":"","loc":"interface/resize.html"},{"title":"has_manifest – Fortran-lang/fpm","text":"function has_manifest(dir) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir Return Value logical Source Code function has_manifest ( dir ) character ( len =* ), intent ( in ) :: dir logical :: has_manifest has_manifest = exists ( join_path ( dir , \"fpm.toml\" )) end function has_manifest","tags":"","loc":"proc/has_manifest.html"},{"title":"get_working_dir – Fortran-lang/fpm","text":"subroutine get_working_dir(settings, working_dir_) Save access to working directory in settings, in case setting have not been allocated Arguments Type Intent Optional Attributes Name class( fpm_cmd_settings ), intent(in), optional :: settings character(len=:), intent(out), allocatable :: working_dir_ Source Code subroutine get_working_dir ( settings , working_dir_ ) class ( fpm_cmd_settings ), optional , intent ( in ) :: settings character ( len = :), allocatable , intent ( out ) :: working_dir_ if ( present ( settings )) then working_dir_ = settings % working_dir end if end subroutine get_working_dir","tags":"","loc":"proc/get_working_dir.html"},{"title":"handle_error – Fortran-lang/fpm","text":"subroutine handle_error(error_) Arguments Type Intent Optional Attributes Name type( error_t ), intent(in), optional :: error_ Source Code subroutine handle_error ( error_ ) type ( error_t ), optional , intent ( in ) :: error_ if ( present ( error_ )) then write ( error_unit , '(\"[Error]\", 1x, a)' ) error_ % message stop 1 end if end subroutine handle_error","tags":"","loc":"proc/handle_error.html"},{"title":"regex_version_from_text – Fortran-lang/fpm","text":"public function regex_version_from_text(text, what, error) result(ver) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: text character(len=*), intent(in) :: what type( error_t ), intent(out), allocatable :: error Return Value type( string_t ) Source Code type ( string_t ) function regex_version_from_text ( text , what , error ) result ( ver ) character ( * ), intent ( in ) :: text character ( * ), intent ( in ) :: what type ( error_t ), allocatable , intent ( out ) :: error integer :: ire , length if ( len_trim ( text ) <= 0 ) then call syntax_error ( error , 'cannot retrieve ' // what // ' version: empty input string' ) return end if ! Extract 3-sized version \"1.0.4\" ire = regex ( text , '\\d+\\.\\d+\\.\\d+' , length = length ) if ( ire > 0 . and . length > 0 ) then ! Parse version into the object (this should always work) ver = string_t ( text ( ire : ire + length - 1 )) else ! Try 2-sized version \"1.0\" ire = regex ( text , '\\d+\\.\\d+' , length = length ) if ( ire > 0 . and . length > 0 ) then ver = string_t ( text ( ire : ire + length - 1 )) else call syntax_error ( error , 'cannot retrieve ' // what // ' version.' ) end if end if end function regex_version_from_text","tags":"","loc":"proc/regex_version_from_text.html"},{"title":"new_version – Fortran-lang/fpm","text":"public interface new_version Module Procedures private subroutine new_version_from_string(self, string, error) Create a new version from a string Arguments Type Intent Optional Attributes Name type( version_t ), intent(out) :: self Instance of the versioning data character(len=*), intent(in) :: string String describing the version information type( error_t ), intent(out), allocatable :: error Error handling private subroutine new_version_from_int(self, num) Create a new version from a string Arguments Type Intent Optional Attributes Name type( version_t ), intent(out) :: self Instance of the versioning data integer, intent(in) :: num (:) Subversion numbers to define version data","tags":"","loc":"interface/new_version.html"},{"title":"descriptor_name – Fortran-lang/fpm","text":"public pure function descriptor_name(descriptor) result(name) Code git descriptor to a string Arguments Type Intent Optional Attributes Name integer, intent(in) :: descriptor Return Value character(len=:), allocatable Source Code pure function descriptor_name ( descriptor ) result ( name ) integer , intent ( in ) :: descriptor character ( len = :), allocatable :: name select case ( descriptor ) case ( git_descriptor % default ); name = \"default\" case ( git_descriptor % branch ); name = \"branch\" case ( git_descriptor % tag ); name = \"tag\" case ( git_descriptor % revision ); name = \"revision\" case default ; name = \"ERROR\" end select end function descriptor_name","tags":"","loc":"proc/descriptor_name.html"},{"title":"git_is_same – Fortran-lang/fpm","text":"public function git_is_same(this, that) Check that two git targets are equal\nAll checks passed! Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Source Code logical function git_is_same ( this , that ) class ( git_target_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that git_is_same = . false . select type ( other => that ) type is ( git_target_t ) if (. not .( this % descriptor == other % descriptor )) return if (. not .( this % url == other % url )) return if (. not .( this % object == other % object )) return class default ! Not the same type return end select !> All checks passed! git_is_same = . true . end function git_is_same","tags":"","loc":"proc/git_is_same.html"},{"title":"git_matches_manifest – Fortran-lang/fpm","text":"public function git_matches_manifest(cached, manifest, verbosity, iunit) Check that a cached dependency matches a manifest request The manifest dependency only contains partial information (what’s requested),\nwhile the cached dependency always stores a commit hash because it’s built\nafter the repo is available (saved as git_descriptor%revision==revision).\nSo, comparing against the descriptor is not reliable Arguments Type Intent Optional Attributes Name type( git_target_t ), intent(in) :: cached Two input git targets type( git_target_t ), intent(in) :: manifest Two input git targets integer, intent(in) :: verbosity integer, intent(in) :: iunit Return Value logical Source Code logical function git_matches_manifest ( cached , manifest , verbosity , iunit ) !> Two input git targets type ( git_target_t ), intent ( in ) :: cached , manifest integer , intent ( in ) :: verbosity , iunit git_matches_manifest = cached % url == manifest % url if (. not . git_matches_manifest ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT URL has changed: \" , cached % url , \" vs. \" , manifest % url return endif !> The manifest dependency only contains partial information (what's requested), !> while the cached dependency always stores a commit hash because it's built !> after the repo is available (saved as git_descriptor%revision==revision). !> So, comparing against the descriptor is not reliable git_matches_manifest = allocated ( cached % object ) . eqv . allocated ( manifest % object ) if ( git_matches_manifest . and . allocated ( cached % object )) & git_matches_manifest = cached % object == manifest % object if (. not . git_matches_manifest ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT OBJECT has changed: \" , cached % object , \" vs. \" , manifest % object end if end function git_matches_manifest","tags":"","loc":"proc/git_matches_manifest.html"},{"title":"git_target_branch – Fortran-lang/fpm","text":"public function git_target_branch(url, branch) result(self) Target a branch in the git repository Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: branch Name of the branch of interest Return Value type( git_target_t ) New git target Source Code function git_target_branch ( url , branch ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Name of the branch of interest character ( len =* ), intent ( in ) :: branch !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % branch self % url = url self % object = branch end function git_target_branch","tags":"","loc":"proc/git_target_branch.html"},{"title":"git_target_default – Fortran-lang/fpm","text":"public function git_target_default(url) result(self) Default target Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository Return Value type( git_target_t ) New git target Source Code function git_target_default ( url ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % default self % url = url end function git_target_default","tags":"","loc":"proc/git_target_default.html"},{"title":"git_target_revision – Fortran-lang/fpm","text":"public function git_target_revision(url, sha1) result(self) Target a specific git revision Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: sha1 Commit hash of interest Return Value type( git_target_t ) New git target Source Code function git_target_revision ( url , sha1 ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Commit hash of interest character ( len =* ), intent ( in ) :: sha1 !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % revision self % url = url self % object = sha1 end function git_target_revision","tags":"","loc":"proc/git_target_revision.html"},{"title":"git_target_tag – Fortran-lang/fpm","text":"public function git_target_tag(url, tag) result(self) Target a git tag Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: tag Tag name of interest Return Value type( git_target_t ) New git target Source Code function git_target_tag ( url , tag ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Tag name of interest character ( len =* ), intent ( in ) :: tag !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % tag self % url = url self % object = tag end function git_target_tag","tags":"","loc":"proc/git_target_tag.html"},{"title":"parse_descriptor – Fortran-lang/fpm","text":"public pure function parse_descriptor(name) Parse git descriptor identifier from a string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Return Value integer Source Code pure integer function parse_descriptor ( name ) character ( len =* ), intent ( in ) :: name select case ( name ) case ( \"default\" ); parse_descriptor = git_descriptor % default case ( \"branch\" ); parse_descriptor = git_descriptor % branch case ( \"tag\" ); parse_descriptor = git_descriptor % tag case ( \"revision\" ); parse_descriptor = git_descriptor % revision case default ; parse_descriptor = git_descriptor % error end select end function parse_descriptor","tags":"","loc":"proc/parse_descriptor.html"},{"title":"checkout – Fortran-lang/fpm","text":"public subroutine checkout(self, local_path, error) Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target character(len=*), intent(in) :: local_path Local path to checkout in type( error_t ), intent(out), allocatable :: error Error Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: object integer, public :: stat character(len=:), public, allocatable :: workdir Source Code subroutine checkout ( self , local_path , error ) !> Instance of the git target class ( git_target_t ), intent ( in ) :: self !> Local path to checkout in character ( * ), intent ( in ) :: local_path !> Error type ( error_t ), allocatable , intent ( out ) :: error integer :: stat character ( len = :), allocatable :: object , workdir if ( allocated ( self % object )) then object = self % object else object = 'HEAD' end if workdir = \"--work-tree=\" // local_path // \" --git-dir=\" // join_path ( local_path , \".git\" ) call execute_command_line ( \"git init \" // local_path , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while initiating git repository for remote dependency' ) return end if call execute_command_line ( \"git \" // workdir // \" fetch --depth=1 \" // & self % url // \" \" // object , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while fetching git repository for remote dependency' ) return end if call execute_command_line ( \"git \" // workdir // \" checkout -qf FETCH_HEAD\" , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while checking out git repository for remote dependency' ) return end if end subroutine checkout","tags":"","loc":"proc/checkout.html"},{"title":"dump_to_toml – Fortran-lang/fpm","text":"public subroutine dump_to_toml(self, table, error) Dump dependency to toml table Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ierr Source Code subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( git_target_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_string ( table , \"descriptor\" , descriptor_name ( self % descriptor ), error , 'git_target_t' ) if ( allocated ( error )) return call set_string ( table , \"url\" , self % url , error , 'git_target_t' ) if ( allocated ( error )) return call set_string ( table , \"object\" , self % object , error , 'git_target_t' ) if ( allocated ( error )) return end subroutine dump_to_toml","tags":"","loc":"proc/dump_to_toml~4.html"},{"title":"git_archive – Fortran-lang/fpm","text":"public subroutine git_archive(source, destination, ref, additional_files, verbose, error) Archive a folder using git archive . Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: source Directory to archive. character(len=*), intent(in) :: destination Destination of the archive. character(len=*), intent(in) :: ref (Symbolic) Reference to be archived. character(len=*), intent(in), optional :: additional_files (:) (Optional) list of additional untracked files to be added to the archive. logical, intent(in) :: verbose Print additional information if true. type( error_t ), intent(out), allocatable :: error Error handling. Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: add_files character(len=:), public, allocatable :: archive_format character(len=:), public, allocatable :: cmd_output integer, public :: i integer, public :: stat","tags":"","loc":"proc/git_archive.html"},{"title":"git_revision – Fortran-lang/fpm","text":"public subroutine git_revision(local_path, object, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: local_path Local path to checkout in character(len=:), intent(out), allocatable :: object Git object reference type( error_t ), intent(out), allocatable :: error Error Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: hexdigits = '0123456789abcdef' integer, public :: iend character(len=:), public, allocatable :: iomsg integer, public :: istart character(len=:), public, allocatable :: line integer, public :: stat character(len=:), public, allocatable :: temp_file integer, public :: unit character(len=:), public, allocatable :: workdir Source Code subroutine git_revision ( local_path , object , error ) !> Local path to checkout in character ( * ), intent ( in ) :: local_path !> Git object reference character ( len = :), allocatable , intent ( out ) :: object !> Error type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , unit , istart , iend character ( len = :), allocatable :: temp_file , line , iomsg , workdir character ( len =* ), parameter :: hexdigits = '0123456789abcdef' workdir = \"--work-tree=\" // local_path // \" --git-dir=\" // join_path ( local_path , \".git\" ) allocate ( temp_file , source = get_temp_filename ()) line = \"git \" // workdir // \" log -n 1 > \" // temp_file call execute_command_line ( line , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error while retrieving commit information\" ) return end if open ( file = temp_file , newunit = unit ) call getline ( unit , line , stat , iomsg ) if ( stat /= 0 ) then call fatal_error ( error , iomsg ) return end if close ( unit , status = \"delete\" ) ! Tokenize: ! commit 0123456789abcdef (HEAD, ...) istart = scan ( line , ' ' ) + 1 iend = verify ( line ( istart :), hexdigits ) + istart - 1 if ( iend < istart ) iend = len ( line ) object = line ( istart : iend ) end subroutine git_revision","tags":"","loc":"proc/git_revision.html"},{"title":"info – Fortran-lang/fpm","text":"public subroutine info(self, unit, verbosity) Show information on git target Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: fmt = '(\"#\", 1x, a, t30, a)' integer, public :: pr Source Code subroutine info ( self , unit , verbosity ) !> Instance of the git target class ( git_target_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Git target\" if ( allocated ( self % url )) then write ( unit , fmt ) \"- URL\" , self % url end if if ( allocated ( self % object )) then select case ( self % descriptor ) case default write ( unit , fmt ) \"- object\" , self % object case ( git_descriptor % tag ) write ( unit , fmt ) \"- tag\" , self % object case ( git_descriptor % branch ) write ( unit , fmt ) \"- branch\" , self % object case ( git_descriptor % revision ) write ( unit , fmt ) \"- sha1\" , self % object end select end if end subroutine info","tags":"","loc":"proc/info~4.html"},{"title":"load_from_toml – Fortran-lang/fpm","text":"public subroutine load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Target URL of the git repository Additional descriptor of the git object Type Bound git_target_t Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: descriptor_name Local variables Source Code subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( git_target_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: descriptor_name call get_value ( table , \"descriptor\" , descriptor_name ) self % descriptor = parse_descriptor ( descriptor_name ) if ( self % descriptor == git_descriptor % error ) then call fatal_error ( error , \"invalid descriptor ID <\" // descriptor_name // \"> in TOML entry\" ) return end if !> Target URL of the git repository call get_value ( table , \"url\" , self % url ) !> Additional descriptor of the git object call get_value ( table , \"object\" , self % object ) end subroutine load_from_toml","tags":"","loc":"proc/load_from_toml~4.html"},{"title":"new_installer – Fortran-lang/fpm","text":"public subroutine new_installer(self, prefix, bindir, libdir, includedir, verbosity, copy, move) Create a new instance of an installer Arguments Type Intent Optional Attributes Name type( installer_t ), intent(out) :: self Instance of the installer character(len=*), intent(in), optional :: prefix Path to installation directory character(len=*), intent(in), optional :: bindir Binary dir relative to the installation prefix character(len=*), intent(in), optional :: libdir Library directory relative to the installation prefix character(len=*), intent(in), optional :: includedir Include directory relative to the installation prefix integer, intent(in), optional :: verbosity Verbosity of the installer character(len=*), intent(in), optional :: copy Copy command character(len=*), intent(in), optional :: move Move command Source Code subroutine new_installer ( self , prefix , bindir , libdir , includedir , verbosity , & copy , move ) !> Instance of the installer type ( installer_t ), intent ( out ) :: self !> Path to installation directory character ( len =* ), intent ( in ), optional :: prefix !> Binary dir relative to the installation prefix character ( len =* ), intent ( in ), optional :: bindir !> Library directory relative to the installation prefix character ( len =* ), intent ( in ), optional :: libdir !> Include directory relative to the installation prefix character ( len =* ), intent ( in ), optional :: includedir !> Verbosity of the installer integer , intent ( in ), optional :: verbosity !> Copy command character ( len =* ), intent ( in ), optional :: copy !> Move command character ( len =* ), intent ( in ), optional :: move self % os = get_os_type () ! By default, never prompt the user for overwrites if ( present ( copy )) then self % copy = copy else if ( os_is_unix ( self % os )) then self % copy = default_force_copy_unix else self % copy = default_force_copy_win end if end if if ( present ( move )) then self % move = move else if ( os_is_unix ( self % os )) then self % move = default_move_unix else self % move = default_move_win end if end if if ( present ( includedir )) then self % includedir = includedir else self % includedir = default_includedir end if if ( present ( prefix )) then self % prefix = prefix else self % prefix = get_local_prefix ( self % os ) end if if ( present ( bindir )) then self % bindir = bindir else self % bindir = default_bindir end if if ( present ( libdir )) then self % libdir = libdir else self % libdir = default_libdir end if if ( present ( verbosity )) then self % verbosity = verbosity else self % verbosity = 1 end if end subroutine new_installer","tags":"","loc":"proc/new_installer.html"},{"title":"default_example – Fortran-lang/fpm","text":"public subroutine default_example(self, name) Populate test in case we find the default example/ directory Arguments Type Intent Optional Attributes Name type( example_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package Source Code subroutine default_example ( self , name ) !> Instance of the executable meta data type ( example_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name // \"-demo\" self % source_dir = \"example\" self % main = \"main.f90\" end subroutine default_example","tags":"","loc":"proc/default_example.html"},{"title":"default_executable – Fortran-lang/fpm","text":"public subroutine default_executable(self, name) Populate executable in case we find the default app directory Arguments Type Intent Optional Attributes Name type( executable_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package Source Code subroutine default_executable ( self , name ) !> Instance of the executable meta data type ( executable_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name self % source_dir = \"app\" self % main = \"main.f90\" end subroutine default_executable","tags":"","loc":"proc/default_executable.html"},{"title":"default_library – Fortran-lang/fpm","text":"public subroutine default_library(self) Populate library in case we find the default src directory Arguments Type Intent Optional Attributes Name type( library_config_t ), intent(out) :: self Instance of the library meta data Source Code subroutine default_library ( self ) !> Instance of the library meta data type ( library_config_t ), intent ( out ) :: self self % source_dir = \"src\" self % include_dir = [ string_t ( \"include\" )] end subroutine default_library","tags":"","loc":"proc/default_library.html"},{"title":"default_test – Fortran-lang/fpm","text":"public subroutine default_test(self, name) Populate test in case we find the default test/ directory Arguments Type Intent Optional Attributes Name type( test_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package Source Code subroutine default_test ( self , name ) !> Instance of the executable meta data type ( test_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name // \"-test\" self % source_dir = \"test\" self % main = \"main.f90\" end subroutine default_test","tags":"","loc":"proc/default_test.html"},{"title":"get_package_data – Fortran-lang/fpm","text":"public subroutine get_package_data(package, file, error, apply_defaults) Obtain package meta data from a configuation file Arguments Type Intent Optional Attributes Name type( package_config_t ), intent(out) :: package Parsed package meta data character(len=*), intent(in) :: file Name of the package configuration file type( error_t ), intent(out), allocatable :: error Error status of the operation logical, intent(in), optional :: apply_defaults Apply package defaults (uses file system operations) Source Code subroutine get_package_data ( package , file , error , apply_defaults ) !> Parsed package meta data type ( package_config_t ), intent ( out ) :: package !> Name of the package configuration file character ( len =* ), intent ( in ) :: file !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error !> Apply package defaults (uses file system operations) logical , intent ( in ), optional :: apply_defaults type ( toml_table ), allocatable :: table character ( len = :), allocatable :: root call read_package_file ( table , file , error ) if ( allocated ( error )) return if (. not . allocated ( table )) then call fatal_error ( error , \"Unclassified error while reading: '\" // file // \"'\" ) return end if call new_package ( package , table , dirname ( file ), error ) if ( allocated ( error )) return if ( present ( apply_defaults )) then if ( apply_defaults ) then root = dirname ( file ) if ( len_trim ( root ) == 0 ) root = \".\" call package_defaults ( package , root , error ) if ( allocated ( error )) return end if end if end subroutine get_package_data","tags":"","loc":"proc/get_package_data.html"},{"title":"new_package – Fortran-lang/fpm","text":"public subroutine new_package(self, table, root, error) Construct a new package configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( package_config_t ), intent(out) :: self Instance of the package configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_package ( self , table , root , error ) !> Instance of the package configuration type ( package_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( len =* ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error ! Backspace (8), tabulator (9), newline (10), formfeed (12) and carriage ! return (13) are invalid in package names character ( len =* ), parameter :: invalid_chars = & achar ( 8 ) // achar ( 9 ) // achar ( 10 ) // achar ( 12 ) // achar ( 13 ) type ( toml_table ), pointer :: child , node type ( toml_array ), pointer :: children character ( len = :), allocatable :: version , version_file integer :: ii , nn , stat , io call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve package name\" ) return end if if ( bad_name_error ( error , 'package' , self % name )) then return endif call get_value ( table , \"license\" , self % license ) call get_value ( table , \"author\" , self % author ) call get_value ( table , \"maintainer\" , self % maintainer ) call get_value ( table , \"copyright\" , self % copyright ) if ( len ( self % name ) <= 0 ) then call syntax_error ( error , \"Package name must be a non-empty string\" ) return end if ii = scan ( self % name , invalid_chars ) if ( ii > 0 ) then call syntax_error ( error , \"Package name contains invalid characters\" ) return end if call get_value ( table , \"build\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for build entry, must be a table\" ) return end if call new_build_config ( self % build , child , self % name , error ) if ( allocated ( error )) return call get_value ( table , \"install\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for install entry, must be a table\" ) return end if call new_install_config ( self % install , child , error ) if ( allocated ( error )) return call get_value ( table , \"fortran\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for fortran entry, must be a table\" ) return end if call new_fortran_config ( self % fortran , child , error ) if ( allocated ( error )) return call get_value ( table , \"version\" , version , \"0\" ) call new_version ( self % version , version , error ) if ( allocated ( error ) . and . present ( root )) then version_file = join_path ( root , version ) if ( exists ( version_file )) then deallocate ( error ) open ( file = version_file , newunit = io , iostat = stat ) if ( stat == 0 ) then call getline ( io , version , iostat = stat ) end if if ( stat == 0 ) then close ( io , iostat = stat ) end if if ( stat == 0 ) then call new_version ( self % version , version , error ) else call fatal_error ( error , \"Reading version number from file '\" & & // version_file // \"' failed\" ) end if end if end if if ( allocated ( error )) return call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , root , self % meta , error ) if ( allocated ( error )) return end if call get_value ( table , \"dev-dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dev_dependency , child , root , error = error ) if ( allocated ( error )) return end if call get_value ( table , \"library\" , child , requested = . false .) if ( associated ( child )) then allocate ( self % library ) call new_library ( self % library , child , error ) if ( allocated ( error )) return end if call get_value ( table , \"profiles\" , child , requested = . false .) if ( associated ( child )) then call new_profiles ( self % profiles , child , error ) if ( allocated ( error )) return else self % profiles = get_default_profiles ( error ) if ( allocated ( error )) return end if call get_value ( table , \"executable\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % executable ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve executable from array entry\" ) exit end if call new_executable ( self % executable ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % executable , error ) if ( allocated ( error )) return end if call get_value ( table , \"example\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % example ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve example from array entry\" ) exit end if call new_example ( self % example ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % example , error ) if ( allocated ( error )) return if ( allocated ( self % executable )) then call unique_programs ( self % executable , self % example , error ) if ( allocated ( error )) return end if end if call get_value ( table , \"test\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % test ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve test from array entry\" ) exit end if call new_test ( self % test ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % test , error ) if ( allocated ( error )) return end if call get_value ( table , \"preprocess\" , child , requested = . false .) if ( associated ( child )) then call new_preprocessors ( self % preprocess , child , error ) if ( allocated ( error )) return end if end subroutine new_package","tags":"","loc":"proc/new_package.html"},{"title":"name_is_json – Fortran-lang/fpm","text":"public function name_is_json(filename) Choose between JSON or TOML based on a file name Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value logical Source Code logical function name_is_json ( filename ) character ( * ), intent ( in ) :: filename character ( * ), parameter :: json_identifier = \".json\" name_is_json = . false . if ( len_trim ( filename ) < len ( json_identifier )) return name_is_json = str_ends_with ( lower ( filename ), json_identifier ) end function name_is_json","tags":"","loc":"proc/name_is_json.html"},{"title":"check_keys – Fortran-lang/fpm","text":"public subroutine check_keys(table, valid_keys, error) Check if table contains only keys that are part of the list. If a key is\nfound that is not part of the list, an error is allocated. Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: valid_keys (:) List of keys to check. type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine check_keys ( table , valid_keys , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys to check. character ( len =* ), intent ( in ) :: valid_keys (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: keys (:) type ( toml_table ), pointer :: child character (:), allocatable :: name , value , valid_keys_string integer :: ikey , ivalid call table % get_key ( name ) call table % get_keys ( keys ) do ikey = 1 , size ( keys ) if (. not . any ( keys ( ikey )% key == valid_keys )) then ! Generate error message valid_keys_string = new_line ( 'a' ) // new_line ( 'a' ) do ivalid = 1 , size ( valid_keys ) valid_keys_string = valid_keys_string // trim ( valid_keys ( ivalid )) // new_line ( 'a' ) end do allocate ( error ) error % message = \"Key '\" // keys ( ikey )% key // \"' not allowed in the '\" // & & name // \"' table.\" // new_line ( 'a' ) // new_line ( 'a' ) // 'Valid keys: ' // valid_keys_string return end if ! Check if value can be mapped or else (wrong type) show error message with the error location. ! Right now, it can only be mapped to a string or to a child node, but this can be extended in the future. call get_value ( table , keys ( ikey )% key , value ) if (. not . allocated ( value )) then ! If value is not a string, check if it is a child node call get_value ( table , keys ( ikey )% key , child ) if (. not . associated ( child )) then allocate ( error ) error % message = \"'\" // name // \"' has an invalid '\" // keys ( ikey )% key // \"' entry.\" return endif end if end do end subroutine check_keys","tags":"","loc":"proc/check_keys.html"},{"title":"get_list – Fortran-lang/fpm","text":"public subroutine get_list(table, key, list, error) Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key Key to read from type( string_t ), intent(out), allocatable :: list (:) List of strings to read type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine get_list ( table , key , list , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Key to read from character ( len =* ), intent ( in ) :: key !> List of strings to read type ( string_t ), allocatable , intent ( out ) :: list (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , ilist , nlist type ( toml_array ), pointer :: children character ( len = :), allocatable :: str if (. not . table % has_key ( key )) return call get_value ( table , key , children , requested = . false .) if ( associated ( children )) then nlist = len ( children ) allocate ( list ( nlist )) do ilist = 1 , nlist call get_value ( children , ilist , str , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Entry in \" // key // \" field cannot be read\" ) exit end if call move_alloc ( str , list ( ilist )% s ) end do if ( allocated ( error )) return else call get_value ( table , key , str , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Entry in \" // key // \" field cannot be read\" ) return end if if ( allocated ( str )) then allocate ( list ( 1 )) call move_alloc ( str , list ( 1 )% s ) end if end if end subroutine get_list","tags":"","loc":"proc/get_list.html"},{"title":"read_package_file – Fortran-lang/fpm","text":"public subroutine read_package_file(table, manifest, error) Process the configuration file to a TOML data structure Arguments Type Intent Optional Attributes Name type(toml_table), intent(out), allocatable :: table TOML data structure character(len=*), intent(in) :: manifest Name of the package configuration file type( error_t ), intent(out), allocatable :: error Error status of the operation Source Code subroutine read_package_file ( table , manifest , error ) !> TOML data structure type ( toml_table ), allocatable , intent ( out ) :: table !> Name of the package configuration file character ( len =* ), intent ( in ) :: manifest !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error type ( toml_error ), allocatable :: parse_error integer :: unit logical :: exist inquire ( file = manifest , exist = exist ) if (. not . exist ) then call file_not_found_error ( error , manifest ) return end if open ( file = manifest , newunit = unit ) call toml_load ( table , unit , error = parse_error ) close ( unit ) if ( allocated ( parse_error )) then allocate ( error ) call move_alloc ( parse_error % message , error % message ) return end if end subroutine read_package_file","tags":"","loc":"proc/read_package_file.html"},{"title":"set_list – Fortran-lang/fpm","text":"public subroutine set_list(table, key, list, error) Set no key if array is not present Check the key is not empty\nString array Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the toml table character(len=*), intent(in) :: key Key to save to type( string_t ), intent(in), allocatable :: list (:) Instance of the string array type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine set_list ( table , key , list , error ) !> Instance of the string array type ( string_t ), allocatable , intent ( in ) :: list (:) !> Key to save to character ( len =* ), intent ( in ) :: key !> Instance of the toml table type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: stat , ilist type ( toml_array ), pointer :: children character ( len = :), allocatable :: str !> Set no key if array is not present if (. not . allocated ( list )) return !> Check the key is not empty if ( len_trim ( key ) <= 0 ) then call fatal_error ( error , 'key is empty dumping string array to TOML table' ) return end if if ( size ( list ) /= 1 ) then ! includes empty list case !> String array call add_array ( table , key , children , stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Cannot set array table in \" // key // \" field\" ) return end if do ilist = 1 , size ( list ) call set_value ( children , ilist , list ( ilist )% s , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Cannot store array entry in \" // key // \" field\" ) return end if end do else ! Single value: set string call set_value ( table , key , list ( 1 )% s , stat = stat ) if ( stat /= toml_stat % success ) & call fatal_error ( error , \"Cannot store entry in \" // key // \" field\" ) return end if end subroutine set_list","tags":"","loc":"proc/set_list.html"},{"title":"add_table – Fortran-lang/fpm","text":"public interface add_table add_table: fpm interface Module Procedures private subroutine add_table_fpm(table, key, ptr, error, whereAt) Function wrapper to add a toml table and return an fpm error Nullify pointer Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key Table key type(toml_table), intent(out), pointer :: ptr The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description","tags":"","loc":"interface/add_table.html"},{"title":"get_value – Fortran-lang/fpm","text":"public interface get_value get_value: fpm interface Module Procedures private subroutine get_logical(table, key, var, error, whereAt) Function wrapper to get a logical variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key logical, intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine get_integer(table, key, var, error, whereAt) Function wrapper to get a default integer variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer, intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine get_integer_64(table, key, var, error, whereAt) Function wrapper to get a integer(int64) variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer(kind=int64), intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description","tags":"","loc":"interface/get_value.html"},{"title":"set_string – Fortran-lang/fpm","text":"public interface set_string Module Procedures private subroutine set_character(table, key, var, error, whereAt) Function wrapper to set a character(len=:), allocatable variable to a toml table Check the key is not empty Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key List of keys to check. character(len=*), intent(in), optional :: var The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_string_type(table, key, var, error, whereAt) Function wrapper to set a character(len=:), allocatable variable to a toml table Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key List of keys to check. type( string_t ), intent(in) :: var The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description","tags":"","loc":"interface/set_string.html"},{"title":"set_value – Fortran-lang/fpm","text":"public interface set_value set_value: fpm interface Module Procedures private subroutine set_logical(table, key, var, error, whereAt) Function wrapper to set a logical variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key logical, intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_integer(table, key, var, error, whereAt) Function wrapper to set a default integer variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer, intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_integer_64(table, key, var, error, whereAt) Function wrapper to set a default integer variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer(kind=int64), intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description","tags":"","loc":"interface/set_value.html"},{"title":"cmd_install – Fortran-lang/fpm","text":"public subroutine cmd_install(settings) Entry point for the fpm-install subcommand Arguments Type Intent Optional Attributes Name type( fpm_install_settings ), intent(inout) :: settings Representation of the command line settings Source Code subroutine cmd_install ( settings ) !> Representation of the command line settings type ( fpm_install_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( error_t ), allocatable :: error type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( installer_t ) :: installer type ( string_t ), allocatable :: list (:) logical :: installable integer :: ntargets call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) call build_model ( model , settings , package , error ) call handle_error ( error ) call targets_from_sources ( targets , model , settings % prune , error ) call handle_error ( error ) call install_info ( output_unit , settings % list , targets , ntargets ) if ( settings % list ) return installable = ( allocated ( package % library ) . and . package % install % library ) & . or . allocated ( package % executable ) . or . ntargets > 0 if (. not . installable ) then call fatal_error ( error , \"Project does not contain any installable targets\" ) call handle_error ( error ) end if if (. not . settings % no_rebuild ) then call build_package ( targets , model , verbose = settings % verbose ) end if call new_installer ( installer , prefix = settings % prefix , & bindir = settings % bindir , libdir = settings % libdir , & includedir = settings % includedir , & verbosity = merge ( 2 , 1 , settings % verbose )) if ( allocated ( package % library ) . and . package % install % library ) then call filter_library_targets ( targets , list ) if ( size ( list ) > 0 ) then call installer % install_library ( list ( 1 )% s , error ) call handle_error ( error ) call install_module_files ( installer , targets , error ) call handle_error ( error ) end if end if if ( allocated ( package % executable ) . or . ntargets > 0 ) then call install_executables ( installer , targets , error ) call handle_error ( error ) end if end subroutine cmd_install","tags":"","loc":"proc/cmd_install.html"},{"title":"file_scope_same – Fortran-lang/fpm","text":"public function file_scope_same(this, that) All checks passed! Type Bound file_scope_flag Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Source Code logical function file_scope_same ( this , that ) class ( file_scope_flag ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that file_scope_same = . false . select type ( other => that ) type is ( file_scope_flag ) if ( allocated ( this % file_name ). neqv . allocated ( other % file_name )) return if ( allocated ( this % file_name )) then if (. not .( this % file_name == other % file_name )) return endif if ( allocated ( this % flags ). neqv . allocated ( other % flags )) return if ( allocated ( this % flags )) then if (. not .( this % flags == other % flags )) return endif class default ! Not the same type return end select !> All checks passed! file_scope_same = . true . end function file_scope_same","tags":"","loc":"proc/file_scope_same.html"},{"title":"get_default_profiles – Fortran-lang/fpm","text":"public function get_default_profiles(error) result(default_profiles) Construct an array of built-in profiles Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Error handling Return Value type( profile_config_t ), allocatable, (:) Source Code function get_default_profiles ( error ) result ( default_profiles ) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( profile_config_t ), allocatable :: default_profiles (:) default_profiles = [ & & new_profile ( 'release' , & & 'caf' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -funroll-loops' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'gfortran' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -funroll-loops -fcoarray=single' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'f95' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'nvfortran' , & & OS_ALL , & & flags = ' -Mbackslash' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifort' , & & OS_ALL , & & flags = ' -fp-model precise -pc64 -align all -error-limit 1 -reentrancy& & threaded -nogen-interfaces -assume byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifort' , & & OS_WINDOWS , & & flags = ' /fp:precise /align:all /error-limit:1 /reentrancy:threaded& & /nogen-interfaces /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifx' , & & OS_ALL , & & flags = ' -fp-model=precise -pc64 -align all -error-limit 1 -reentrancy& & threaded -nogen-interfaces -assume byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /fp:precise /align:all /error-limit:1 /reentrancy:threaded& & /nogen-interfaces /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'nagfor' , & & OS_ALL , & & flags = ' -O4 -coarray=single -PIC' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'lfortran' , & & OS_ALL , & & flags = ' flag_lfortran_opt' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'caf' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -fbacktrace' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'gfortran' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -fbacktrace -fcoarray=single' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'f95' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -Wno-maybe-uninitialized -Wno-uninitialized -fbacktrace' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'nvfortran' , & & OS_ALL , & & flags = ' -Minform=inform -Mbackslash -g -Mbounds -Mchkptr -Mchkstk -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifort' , & & OS_ALL , & & flags = ' -warn all -check all -error-limit 1 -O0 -g -assume byterecl -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifort' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1& & /Od /Z7 /assume:byterecl /traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_ALL , & & flags = ' -warn all -check all -error-limit 1 -O0 -g -assume byterecl -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1 /Od /Z7 /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1 /Od /Z7 /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'lfortran' , & & OS_ALL , & & flags = '' , & & is_built_in = . true .) & &] end function get_default_profiles","tags":"","loc":"proc/get_default_profiles.html"},{"title":"info_profile – Fortran-lang/fpm","text":"public function info_profile(profile) result(s) Print a representation of profile_config_t Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(in) :: profile Profile to be represented Return Value character(len=:), allocatable String representation of given profile Variables Type Visibility Attributes Name Initial integer, public :: i Source Code function info_profile ( profile ) result ( s ) !> Profile to be represented type ( profile_config_t ), intent ( in ) :: profile !> String representation of given profile character (:), allocatable :: s integer :: i s = \"profile_config_t(\" s = s // 'profile_name=\"' // profile % profile_name // '\"' s = s // ', compiler=\"' // profile % compiler // '\"' s = s // \", os_type=\" select case ( profile % os_type ) case ( OS_UNKNOWN ) s = s // \"OS_UNKNOWN\" case ( OS_LINUX ) s = s // \"OS_LINUX\" case ( OS_MACOS ) s = s // \"OS_MACOS\" case ( OS_WINDOWS ) s = s // \"OS_WINDOWS\" case ( OS_CYGWIN ) s = s // \"OS_CYGWIN\" case ( OS_SOLARIS ) s = s // \"OS_SOLARIS\" case ( OS_FREEBSD ) s = s // \"OS_FREEBSD\" case ( OS_OPENBSD ) s = s // \"OS_OPENBSD\" case ( OS_ALL ) s = s // \"OS_ALL\" case default s = s // \"INVALID\" end select if ( allocated ( profile % flags )) s = s // ', flags=\"' // profile % flags // '\"' if ( allocated ( profile % c_flags )) s = s // ', c_flags=\"' // profile % c_flags // '\"' if ( allocated ( profile % cxx_flags )) s = s // ', cxx_flags=\"' // profile % cxx_flags // '\"' if ( allocated ( profile % link_time_flags )) s = s // ', link_time_flags=\"' // profile % link_time_flags // '\"' if ( allocated ( profile % file_scope_flags )) then do i = 1 , size ( profile % file_scope_flags ) s = s // ', flags for ' // profile % file_scope_flags ( i )% file_name // & & ' =\"' // profile % file_scope_flags ( i )% flags // '\"' end do end if s = s // \")\" end function info_profile","tags":"","loc":"proc/info_profile.html"},{"title":"new_profile – Fortran-lang/fpm","text":"public function new_profile(profile_name, compiler, os_type, flags, c_flags, cxx_flags, link_time_flags, file_scope_flags, is_built_in) result(profile) Construct a new profile configuration from a TOML data structure Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: profile_name Name of the profile character(len=*), intent(in) :: compiler Name of the compiler integer, intent(in) :: os_type Type of the OS character(len=*), intent(in), optional :: flags Fortran compiler flags character(len=*), intent(in), optional :: c_flags C compiler flags character(len=*), intent(in), optional :: cxx_flags C++ compiler flags character(len=*), intent(in), optional :: link_time_flags Link time compiler flags type( file_scope_flag ), intent(in), optional :: file_scope_flags (:) File scope flags logical, intent(in), optional :: is_built_in Is this profile one of the built-in ones? Return Value type( profile_config_t ) Source Code function new_profile ( profile_name , compiler , os_type , flags , c_flags , cxx_flags , & link_time_flags , file_scope_flags , is_built_in ) & & result ( profile ) !> Name of the profile character ( len =* ), intent ( in ) :: profile_name !> Name of the compiler character ( len =* ), intent ( in ) :: compiler !> Type of the OS integer , intent ( in ) :: os_type !> Fortran compiler flags character ( len =* ), optional , intent ( in ) :: flags !> C compiler flags character ( len =* ), optional , intent ( in ) :: c_flags !> C++ compiler flags character ( len =* ), optional , intent ( in ) :: cxx_flags !> Link time compiler flags character ( len =* ), optional , intent ( in ) :: link_time_flags !> File scope flags type ( file_scope_flag ), optional , intent ( in ) :: file_scope_flags (:) !> Is this profile one of the built-in ones? logical , optional , intent ( in ) :: is_built_in type ( profile_config_t ) :: profile profile % profile_name = profile_name profile % compiler = compiler profile % os_type = os_type if ( present ( flags )) then profile % flags = flags else profile % flags = \"\" end if if ( present ( c_flags )) then profile % c_flags = c_flags else profile % c_flags = \"\" end if if ( present ( cxx_flags )) then profile % cxx_flags = cxx_flags else profile % cxx_flags = \"\" end if if ( present ( link_time_flags )) then profile % link_time_flags = link_time_flags else profile % link_time_flags = \"\" end if if ( present ( file_scope_flags )) then profile % file_scope_flags = file_scope_flags end if if ( present ( is_built_in )) then profile % is_built_in = is_built_in else profile % is_built_in = . false . end if end function new_profile","tags":"","loc":"proc/new_profile.html"},{"title":"os_type_name – Fortran-lang/fpm","text":"public function os_type_name(os_type) Match lowercase string with name of OS to os_type enum Arguments Type Intent Optional Attributes Name integer, intent(in) :: os_type Enum representing type of OS Return Value character(len=:), allocatable Name of operating system Source Code function os_type_name ( os_type ) !> Name of operating system character ( len = :), allocatable :: os_type_name !> Enum representing type of OS integer , intent ( in ) :: os_type select case ( os_type ) case ( OS_ALL ); os_type_name = \"all\" case default ; os_type_name = lower ( OS_NAME ( os_type )) end select end function os_type_name","tags":"","loc":"proc/os_type_name.html"},{"title":"profile_same – Fortran-lang/fpm","text":"public function profile_same(this, that) All checks passed! Type Bound profile_config_t Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Variables Type Visibility Attributes Name Initial integer, public :: ii Source Code logical function profile_same ( this , that ) class ( profile_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii profile_same = . false . select type ( other => that ) type is ( profile_config_t ) if ( allocated ( this % profile_name ). neqv . allocated ( other % profile_name )) return if ( allocated ( this % profile_name )) then if (. not .( this % profile_name == other % profile_name )) return endif if ( allocated ( this % compiler ). neqv . allocated ( other % compiler )) return if ( allocated ( this % compiler )) then if (. not .( this % compiler == other % compiler )) return endif if ( this % os_type /= other % os_type ) return if ( allocated ( this % flags ). neqv . allocated ( other % flags )) return if ( allocated ( this % flags )) then if (. not .( this % flags == other % flags )) return endif if ( allocated ( this % c_flags ). neqv . allocated ( other % c_flags )) return if ( allocated ( this % c_flags )) then if (. not .( this % c_flags == other % c_flags )) return endif if ( allocated ( this % cxx_flags ). neqv . allocated ( other % cxx_flags )) return if ( allocated ( this % cxx_flags )) then if (. not .( this % cxx_flags == other % cxx_flags )) return endif if ( allocated ( this % link_time_flags ). neqv . allocated ( other % link_time_flags )) return if ( allocated ( this % link_time_flags )) then if (. not .( this % link_time_flags == other % link_time_flags )) return endif if ( allocated ( this % file_scope_flags ). neqv . allocated ( other % file_scope_flags )) return if ( allocated ( this % file_scope_flags )) then if (. not . size ( this % file_scope_flags ) == size ( other % file_scope_flags )) return do ii = 1 , size ( this % file_scope_flags ) print * , 'check ii-th file scope: ' , ii if (. not . this % file_scope_flags ( ii ) == other % file_scope_flags ( ii )) return end do endif if ( this % is_built_in . neqv . other % is_built_in ) return class default ! Not the same type return end select !> All checks passed! profile_same = . true . end function profile_same","tags":"","loc":"proc/profile_same.html"},{"title":"file_scope_dump – Fortran-lang/fpm","text":"public subroutine file_scope_dump(self, table, error) Dump to toml table Type Bound file_scope_flag Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine file_scope_dump ( self , table , error ) !> Instance of the serializable object class ( file_scope_flag ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_string ( table , \"file-name\" , self % file_name , error ) if ( allocated ( error )) return call set_string ( table , \"flags\" , self % flags , error ) if ( allocated ( error )) return end subroutine file_scope_dump","tags":"","loc":"proc/file_scope_dump.html"},{"title":"file_scope_load – Fortran-lang/fpm","text":"public subroutine file_scope_load(self, table, error) Read from toml table (no checks made at this stage) Type Bound file_scope_flag Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine file_scope_load ( self , table , error ) !> Instance of the serializable object class ( file_scope_flag ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"file-name\" , self % file_name ) call get_value ( table , \"flags\" , self % flags ) end subroutine file_scope_load","tags":"","loc":"proc/file_scope_load.html"},{"title":"find_profile – Fortran-lang/fpm","text":"public subroutine find_profile(profiles, profile_name, compiler, os_type, found_matching, chosen_profile) Look for profile with given configuration in array profiles Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(in), allocatable :: profiles (:) Array of profiles character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler Name of compiler integer, intent(in) :: os_type Type of operating system (enum) logical, intent(out) :: found_matching Boolean value containing true if matching profile was found type( profile_config_t ), intent(out) :: chosen_profile Last matching profile in the profiles array Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: curr_compiler integer, public :: curr_os integer, public :: curr_priority character(len=:), public, allocatable :: curr_profile_name integer, public :: i integer, public :: priority Source Code subroutine find_profile ( profiles , profile_name , compiler , os_type , found_matching , chosen_profile ) !> Array of profiles type ( profile_config_t ), allocatable , intent ( in ) :: profiles (:) !> Name of profile character (:), allocatable , intent ( in ) :: profile_name !> Name of compiler character (:), allocatable , intent ( in ) :: compiler !> Type of operating system (enum) integer , intent ( in ) :: os_type !> Boolean value containing true if matching profile was found logical , intent ( out ) :: found_matching !> Last matching profile in the profiles array type ( profile_config_t ), intent ( out ) :: chosen_profile character (:), allocatable :: curr_profile_name character (:), allocatable :: curr_compiler integer :: curr_os integer :: i , priority , curr_priority found_matching = . false . if ( size ( profiles ) < 1 ) return ! Try to find profile with matching OS type do i = 1 , size ( profiles ) curr_profile_name = profiles ( i )% profile_name curr_compiler = profiles ( i )% compiler curr_os = profiles ( i )% os_type if ( curr_profile_name . eq . profile_name ) then if ( curr_compiler . eq . compiler ) then if ( curr_os . eq . os_type ) then chosen_profile = profiles ( i ) found_matching = . true . end if end if end if end do ! Try to find profile with OS type 'all' if (. not . found_matching ) then do i = 1 , size ( profiles ) curr_profile_name = profiles ( i )% profile_name curr_compiler = profiles ( i )% compiler curr_os = profiles ( i )% os_type if ( curr_profile_name . eq . profile_name ) then if ( curr_compiler . eq . compiler ) then if ( curr_os . eq . OS_ALL ) then chosen_profile = profiles ( i ) found_matching = . true . end if end if end if end do end if end subroutine find_profile","tags":"","loc":"proc/find_profile.html"},{"title":"get_flags – Fortran-lang/fpm","text":"public subroutine get_flags(profile_name, compiler_name, os_type, key_list, table, profiles, profindex, os_valid) Look for flags, c-flags, link-time-flags key-val pairs\nand files table in a given table and create new profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler integer, intent(in) :: os_type OS type type(toml_key), intent(in), allocatable :: key_list (:) List of keys in the table type(toml_table), intent(in), pointer :: table Table containing OS tables type( profile_config_t ), intent(inout), allocatable :: profiles (:) List of profiles integer, intent(inout) :: profindex Index in the list of profiles logical, intent(in) :: os_valid Was called with valid operating system Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: c_flags character(len=:), public, allocatable :: cxx_flags character(len=:), public, allocatable :: err_message character(len=:), public, allocatable :: file_flags type(toml_key), public, allocatable :: file_list (:) character(len=:), public, allocatable :: file_name type( file_scope_flag ), public, allocatable :: file_scope_flags (:) type(toml_table), public, pointer :: files character(len=:), public, allocatable :: flags integer, public :: ifile integer, public :: ikey logical, public :: is_valid character(len=:), public, allocatable :: key_name character(len=:), public, allocatable :: link_time_flags integer, public :: stat Source Code subroutine get_flags ( profile_name , compiler_name , os_type , key_list , table , profiles , profindex , os_valid ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> OS type integer , intent ( in ) :: os_type !> List of keys in the table type ( toml_key ), allocatable , intent ( in ) :: key_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ) :: profiles (:) !> Index in the list of profiles integer , intent ( inout ) :: profindex !> Was called with valid operating system logical , intent ( in ) :: os_valid character ( len = :), allocatable :: flags , c_flags , cxx_flags , link_time_flags , key_name , file_name , file_flags , err_message type ( toml_table ), pointer :: files type ( toml_key ), allocatable :: file_list (:) type ( file_scope_flag ), allocatable :: file_scope_flags (:) integer :: ikey , ifile , stat logical :: is_valid call get_value ( table , 'flags' , flags ) call get_value ( table , 'c-flags' , c_flags ) call get_value ( table , 'cxx-flags' , cxx_flags ) call get_value ( table , 'link-time-flags' , link_time_flags ) call get_value ( table , 'files' , files ) if ( associated ( files )) then call files % get_keys ( file_list ) allocate ( file_scope_flags ( size ( file_list ))) do ifile = 1 , size ( file_list ) file_name = file_list ( ifile )% key call get_value ( files , file_name , file_flags ) associate ( cur_file => file_scope_flags ( ifile )) if (. not .( path . eq . \"\" )) file_name = join_path ( path , file_name ) cur_file % file_name = file_name cur_file % flags = file_flags end associate end do end if profiles ( profindex ) = new_profile ( profile_name , compiler_name , os_type , & & flags , c_flags , cxx_flags , link_time_flags , file_scope_flags ) profindex = profindex + 1 end subroutine get_flags","tags":"","loc":"proc/get_flags.html"},{"title":"info – Fortran-lang/fpm","text":"public subroutine info(self, unit, verbosity) Write information on instance Type Bound profile_config_t Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: self Instance of the profile configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: fmt = '(\"#\", 1x, a, t30, a)' integer, public :: pr Source Code subroutine info ( self , unit , verbosity ) !> Instance of the profile configuration class ( profile_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if write ( unit , fmt ) \"Profile\" if ( allocated ( self % profile_name )) then write ( unit , fmt ) \"- profile name\" , self % profile_name end if if ( allocated ( self % compiler )) then write ( unit , fmt ) \"- compiler\" , self % compiler end if write ( unit , fmt ) \"- os\" , os_type_name ( self % os_type ) if ( allocated ( self % flags )) then write ( unit , fmt ) \"- compiler flags\" , self % flags end if end subroutine info","tags":"","loc":"proc/info~6.html"},{"title":"match_os_type – Fortran-lang/fpm","text":"public subroutine match_os_type(os_name, os_type) Match os_type enum to a lowercase string with name of OS Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: os_name Name of operating system integer, intent(out) :: os_type Enum representing type of OS Source Code subroutine match_os_type ( os_name , os_type ) !> Name of operating system character ( len = :), allocatable , intent ( in ) :: os_name !> Enum representing type of OS integer , intent ( out ) :: os_type select case ( os_name ) case ( \"linux\" ); os_type = OS_LINUX case ( \"macos\" ); os_type = OS_MACOS case ( \"windows\" ); os_type = OS_WINDOWS case ( \"cygwin\" ); os_type = OS_CYGWIN case ( \"solaris\" ); os_type = OS_SOLARIS case ( \"freebsd\" ); os_type = OS_FREEBSD case ( \"openbsd\" ); os_type = OS_OPENBSD case ( \"all\" ); os_type = OS_ALL case default ; os_type = OS_UNKNOWN end select end subroutine match_os_type","tags":"","loc":"proc/match_os_type.html"},{"title":"new_profiles – Fortran-lang/fpm","text":"public subroutine new_profiles(profiles, table, error) Construct new profiles array from a TOML data structure Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(out), allocatable :: profiles (:) Instance of the dependency configuration type(toml_table), intent(inout), target :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial type(toml_key), public, allocatable :: comp_list (:) character(len=:), public, allocatable :: compiler_name type( profile_config_t ), public, allocatable :: default_profiles (:) integer, public :: iprof logical, public :: is_valid type(toml_key), public, allocatable :: os_list (:) type(toml_key), public, allocatable :: prof_list (:) type(toml_table), public, pointer :: prof_node character(len=:), public, allocatable :: profile_name integer, public :: profiles_size integer, public :: profindex integer, public :: stat Source Code subroutine new_profiles ( profiles , table , error ) !> Instance of the dependency configuration type ( profile_config_t ), allocatable , intent ( out ) :: profiles (:) !> Instance of the TOML data structure type ( toml_table ), target , intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: prof_node type ( toml_key ), allocatable :: prof_list (:) type ( toml_key ), allocatable :: comp_list (:) type ( toml_key ), allocatable :: os_list (:) character ( len = :), allocatable :: profile_name , compiler_name integer :: profiles_size , iprof , stat , profindex logical :: is_valid type ( profile_config_t ), allocatable :: default_profiles (:) path = '' default_profiles = get_default_profiles ( error ) if ( allocated ( error )) return call table % get_keys ( prof_list ) if ( size ( prof_list ) < 1 ) return profiles_size = 0 do iprof = 1 , size ( prof_list ) profile_name = prof_list ( iprof )% key call validate_compiler_name ( profile_name , is_valid ) if ( is_valid ) then profile_name = \"all\" comp_list = prof_list ( iprof : iprof ) prof_node => table call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles_size = profiles_size ) if ( allocated ( error )) return else call validate_os_name ( profile_name , is_valid ) if ( is_valid ) then os_list = prof_list ( iprof : iprof ) profile_name = 'all' compiler_name = DEFAULT_COMPILER call traverse_oss_for_size ( profile_name , compiler_name , os_list , table , profiles_size , error ) if ( allocated ( error )) return else call get_value ( table , profile_name , prof_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Profile \" // prof_list ( iprof )% key // \" must be a table entry\" ) exit end if call prof_node % get_keys ( comp_list ) call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles_size = profiles_size ) if ( allocated ( error )) return end if end if end do profiles_size = profiles_size + size ( default_profiles ) allocate ( profiles ( profiles_size )) do profindex = 1 , size ( default_profiles ) profiles ( profindex ) = default_profiles ( profindex ) end do do iprof = 1 , size ( prof_list ) profile_name = prof_list ( iprof )% key call validate_compiler_name ( profile_name , is_valid ) if ( is_valid ) then profile_name = \"all\" comp_list = prof_list ( iprof : iprof ) prof_node => table call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles = profiles , profindex = profindex ) if ( allocated ( error )) return else call validate_os_name ( profile_name , is_valid ) if ( is_valid ) then os_list = prof_list ( iprof : iprof ) profile_name = 'all' compiler_name = DEFAULT_COMPILER prof_node => table call traverse_oss ( profile_name , compiler_name , os_list , prof_node , profiles , profindex , error ) if ( allocated ( error )) return else call get_value ( table , profile_name , prof_node , stat = stat ) call prof_node % get_keys ( comp_list ) call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles = profiles , profindex = profindex ) if ( allocated ( error )) return end if end if end do ! Apply profiles with profile name 'all' to matching profiles do iprof = 1 , size ( profiles ) if ( profiles ( iprof )% profile_name . eq . 'all' ) then do profindex = 1 , size ( profiles ) if (. not .( profiles ( profindex )% profile_name . eq . 'all' ) & & . and .( profiles ( profindex )% compiler . eq . profiles ( iprof )% compiler ) & & . and .( profiles ( profindex )% os_type . eq . profiles ( iprof )% os_type )) then profiles ( profindex )% flags = profiles ( profindex )% flags // & & \" \" // profiles ( iprof )% flags profiles ( profindex )% c_flags = profiles ( profindex )% c_flags // & & \" \" // profiles ( iprof )% c_flags profiles ( profindex )% cxx_flags = profiles ( profindex )% cxx_flags // & & \" \" // profiles ( iprof )% cxx_flags profiles ( profindex )% link_time_flags = profiles ( profindex )% link_time_flags // & & \" \" // profiles ( iprof )% link_time_flags end if end do end if end do end subroutine new_profiles","tags":"","loc":"proc/new_profiles.html"},{"title":"profile_dump – Fortran-lang/fpm","text":"public subroutine profile_dump(self, table, error) Dump to toml table Because files need a name, fallback if this has no name Type Bound profile_config_t Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ierr Local variables integer, public :: ii Local variables type(toml_table), public, pointer :: ptr type(toml_table), public, pointer :: ptr_deps character(len=30), public :: unnamed Source Code subroutine profile_dump ( self , table , error ) !> Instance of the serializable object class ( profile_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: ierr , ii type ( toml_table ), pointer :: ptr_deps , ptr character ( len = 30 ) :: unnamed call set_string ( table , \"profile-name\" , self % profile_name , error ) if ( allocated ( error )) return call set_string ( table , \"compiler\" , self % compiler , error ) if ( allocated ( error )) return call set_string ( table , \"os-type\" , os_type_name ( self % os_type ), error , 'profile_config_t' ) if ( allocated ( error )) return call set_string ( table , \"flags\" , self % flags , error ) if ( allocated ( error )) return call set_string ( table , \"c-flags\" , self % c_flags , error ) if ( allocated ( error )) return call set_string ( table , \"cxx-flags\" , self % cxx_flags , error ) if ( allocated ( error )) return call set_string ( table , \"link-time-flags\" , self % link_time_flags , error ) if ( allocated ( error )) return if ( allocated ( self % file_scope_flags )) then ! Create dependency table call add_table ( table , \"file-scope-flags\" , ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , \"profile_config_t cannot create file scope table \" ) return end if do ii = 1 , size ( self % file_scope_flags ) associate ( dep => self % file_scope_flags ( ii )) !> Because files need a name, fallback if this has no name if ( len_trim ( dep % file_name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_deps , trim ( unnamed ), ptr ) else call add_table ( ptr_deps , dep % file_name , ptr ) end if if (. not . associated ( ptr )) then call fatal_error ( error , \"profile_config_t cannot create entry for file \" // dep % file_name ) return end if call dep % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do endif call set_value ( table , \"is-built-in\" , self % is_built_in , error , 'profile_config_t' ) if ( allocated ( error )) return 1 format ( 'UNNAMED_FILE_' , i0 ) end subroutine profile_dump","tags":"","loc":"proc/profile_dump.html"},{"title":"profile_load – Fortran-lang/fpm","text":"public subroutine profile_load(self, table, error) Read from toml table (no checks made at this stage) Read all packages Type Bound profile_config_t Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial type(toml_key), public, allocatable :: dep_keys (:) character(len=:), public, allocatable :: flag Local variables integer, public :: ii integer, public :: jj type(toml_key), public, allocatable :: keys (:) type(toml_table), public, pointer :: ptr type(toml_table), public, pointer :: ptr_dep Source Code subroutine profile_load ( self , table , error ) !> Instance of the serializable object class ( profile_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: flag integer :: ii , jj type ( toml_table ), pointer :: ptr_dep , ptr type ( toml_key ), allocatable :: keys (:), dep_keys (:) call table % get_keys ( keys ) call get_value ( table , \"profile-name\" , self % profile_name ) call get_value ( table , \"compiler\" , self % compiler ) call get_value ( table , \"os-type\" , flag ) call match_os_type ( flag , self % os_type ) call get_value ( table , \"flags\" , self % flags ) call get_value ( table , \"c-flags\" , self % c_flags ) call get_value ( table , \"cxx-flags\" , self % cxx_flags ) call get_value ( table , \"link-time-flags\" , self % link_time_flags ) call get_value ( table , \"is-built-in\" , self % is_built_in , error , 'profile_config_t' ) if ( allocated ( error )) return if ( allocated ( self % file_scope_flags )) deallocate ( self % file_scope_flags ) sub_deps : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"file-scope-flags\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'profile_config_t: error retrieving file_scope_flags table' ) return end if !> Read all packages call ptr % get_keys ( dep_keys ) allocate ( self % file_scope_flags ( size ( dep_keys ))) do jj = 1 , size ( dep_keys ) call get_value ( ptr , dep_keys ( jj ), ptr_dep ) call self % file_scope_flags ( jj )% load_from_toml ( ptr_dep , error ) if ( allocated ( error )) return end do end select end do sub_deps end subroutine profile_load","tags":"","loc":"proc/profile_load.html"},{"title":"traverse_compilers – Fortran-lang/fpm","text":"public subroutine traverse_compilers(profile_name, comp_list, table, error, profiles_size, profiles, profindex) Traverse compiler tables Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile type(toml_key), intent(in), allocatable :: comp_list (:) List of OSs in table with profile name given type(toml_table), intent(in), pointer :: table Table containing compiler tables type( error_t ), intent(out), allocatable :: error Error handling integer, intent(inout), optional :: profiles_size Number of profiles in list of profiles type( profile_config_t ), intent(inout), optional, allocatable :: profiles (:) List of profiles integer, intent(inout), optional :: profindex Index in the list of profiles Variables Type Visibility Attributes Name Initial type(toml_table), public, pointer :: comp_node character(len=:), public, allocatable :: compiler_name integer, public :: icomp logical, public :: is_valid type(toml_key), public, allocatable :: os_list (:) integer, public :: stat Source Code subroutine traverse_compilers ( profile_name , comp_list , table , error , profiles_size , profiles , profindex ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> List of OSs in table with profile name given type ( toml_key ), allocatable , intent ( in ) :: comp_list (:) !> Table containing compiler tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Number of profiles in list of profiles integer , intent ( inout ), optional :: profiles_size !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ), optional :: profiles (:) !> Index in the list of profiles integer , intent ( inout ), optional :: profindex character ( len = :), allocatable :: compiler_name type ( toml_table ), pointer :: comp_node type ( toml_key ), allocatable :: os_list (:) integer :: icomp , stat logical :: is_valid if ( size ( comp_list ) < 1 ) return do icomp = 1 , size ( comp_list ) call validate_compiler_name ( comp_list ( icomp )% key , is_valid ) if ( is_valid ) then compiler_name = comp_list ( icomp )% key call get_value ( table , compiler_name , comp_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Compiler \" // comp_list ( icomp )% key // \" must be a table entry\" ) exit end if call comp_node % get_keys ( os_list ) if ( present ( profiles_size )) then call traverse_oss_for_size ( profile_name , compiler_name , os_list , comp_node , profiles_size , error ) if ( allocated ( error )) return else if (. not .( present ( profiles ). and . present ( profindex ))) then call fatal_error ( error , \"Both profiles and profindex have to be present\" ) return end if call traverse_oss ( profile_name , compiler_name , os_list , comp_node , & & profiles , profindex , error ) if ( allocated ( error )) return end if else call fatal_error ( error , '*traverse_compilers*:Error: Compiler name not specified or invalid.' ) end if end do end subroutine traverse_compilers","tags":"","loc":"proc/traverse_compilers.html"},{"title":"traverse_oss – Fortran-lang/fpm","text":"public subroutine traverse_oss(profile_name, compiler_name, os_list, table, profiles, profindex, error) Traverse operating system tables to obtain profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: os_list (:) List of OSs in table with profile name and compiler name given type(toml_table), intent(in), pointer :: table Table containing OS tables type( profile_config_t ), intent(inout), allocatable :: profiles (:) List of profiles integer, intent(inout) :: profindex Index in the list of profiles type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ios logical, public :: is_key_val logical, public :: is_valid type(toml_key), public, allocatable :: key_list (:) character(len=:), public, allocatable :: l_os_name character(len=:), public, allocatable :: os_name type(toml_table), public, pointer :: os_node integer, public :: os_type integer, public :: stat Source Code subroutine traverse_oss ( profile_name , compiler_name , os_list , table , profiles , profindex , error ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of OSs in table with profile name and compiler name given type ( toml_key ), allocatable , intent ( in ) :: os_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ) :: profiles (:) !> Index in the list of profiles integer , intent ( inout ) :: profindex type ( toml_key ), allocatable :: key_list (:) character ( len = :), allocatable :: os_name , l_os_name type ( toml_table ), pointer :: os_node integer :: ios , stat , os_type logical :: is_valid , is_key_val if ( size ( os_list ) < 1 ) return do ios = 1 , size ( os_list ) os_name = os_list ( ios )% key call validate_os_name ( os_name , is_valid ) if ( is_valid ) then call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"os \" // os_name // \" has to be a table\" ) return end if call os_node % get_keys ( key_list ) call match_os_type ( os_name , os_type ) call get_flags ( profile_name , compiler_name , os_type , key_list , os_node , profiles , profindex , . true .) else ! Not lowercase OS name l_os_name = lower ( os_name ) call validate_os_name ( l_os_name , is_valid ) if ( is_valid ) then call fatal_error ( error , '*traverse_oss*:Error: Name of the operating system must be a lowercase string.' ) end if if ( allocated ( error )) return ! Missing OS name is_key_val = . false . os_name = os_list ( ios )% key call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then is_key_val = . true . end if os_node => table os_type = OS_ALL call get_flags ( profile_name , compiler_name , os_type , os_list , os_node , profiles , profindex , . false .) end if end do end subroutine traverse_oss","tags":"","loc":"proc/traverse_oss.html"},{"title":"traverse_oss_for_size – Fortran-lang/fpm","text":"public subroutine traverse_oss_for_size(profile_name, compiler_name, os_list, table, profiles_size, error) Traverse operating system tables to obtain number of profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: os_list (:) List of OSs in table with profile name and compiler name given type(toml_table), intent(in), pointer :: table Table containing OS tables integer, intent(inout) :: profiles_size Number of profiles in list of profiles type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ios logical, public :: is_key_val logical, public :: is_valid type(toml_key), public, allocatable :: key_list (:) logical, public :: key_val_added character(len=:), public, allocatable :: l_os_name character(len=:), public, allocatable :: os_name type(toml_table), public, pointer :: os_node integer, public :: stat Source Code subroutine traverse_oss_for_size ( profile_name , compiler_name , os_list , table , profiles_size , error ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of OSs in table with profile name and compiler name given type ( toml_key ), allocatable , intent ( in ) :: os_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Number of profiles in list of profiles integer , intent ( inout ) :: profiles_size type ( toml_key ), allocatable :: key_list (:) character ( len = :), allocatable :: os_name , l_os_name type ( toml_table ), pointer :: os_node integer :: ios , stat logical :: is_valid , key_val_added , is_key_val if ( size ( os_list ) < 1 ) return key_val_added = . false . do ios = 1 , size ( os_list ) os_name = os_list ( ios )% key call validate_os_name ( os_name , is_valid ) if ( is_valid ) then call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"os \" // os_name // \" has to be a table\" ) return end if call os_node % get_keys ( key_list ) profiles_size = profiles_size + 1 call validate_profile_table ( profile_name , compiler_name , key_list , os_node , error , . true .) else ! Not lowercase OS name l_os_name = lower ( os_name ) call validate_os_name ( l_os_name , is_valid ) if ( is_valid ) then call fatal_error ( error , '*traverse_oss*:Error: Name of the operating system must be a lowercase string.' ) end if if ( allocated ( error )) return ! Missing OS name is_key_val = . false . os_name = os_list ( ios )% key call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then is_key_val = . true . end if os_node => table if ( is_key_val . and .. not . key_val_added ) then key_val_added = . true . is_key_val = . false . profiles_size = profiles_size + 1 else if (. not . is_key_val ) then profiles_size = profiles_size + 1 end if call validate_profile_table ( profile_name , compiler_name , os_list , os_node , error , . false .) end if end do end subroutine traverse_oss_for_size","tags":"","loc":"proc/traverse_oss_for_size.html"},{"title":"validate_compiler_name – Fortran-lang/fpm","text":"public subroutine validate_compiler_name(compiler_name, is_valid) Check if compiler name is a valid compiler name Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: compiler_name Name of a compiler logical, intent(out) :: is_valid Boolean value of whether compiler_name is valid or not Source Code subroutine validate_compiler_name ( compiler_name , is_valid ) !> Name of a compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> Boolean value of whether compiler_name is valid or not logical , intent ( out ) :: is_valid select case ( compiler_name ) case ( \"gfortran\" , \"ifort\" , \"ifx\" , \"pgfortran\" , \"nvfortran\" , \"flang\" , \"caf\" , & & \"f95\" , \"lfortran\" , \"lfc\" , \"nagfor\" , \"crayftn\" , \"xlf90\" , \"ftn95\" ) is_valid = . true . case default is_valid = . false . end select end subroutine validate_compiler_name","tags":"","loc":"proc/validate_compiler_name.html"},{"title":"validate_os_name – Fortran-lang/fpm","text":"public subroutine validate_os_name(os_name, is_valid) Check if os_name is a valid name of a supported OS Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: os_name Name of an operating system logical, intent(out) :: is_valid Boolean value of whether os_name is valid or not Source Code subroutine validate_os_name ( os_name , is_valid ) !> Name of an operating system character ( len = :), allocatable , intent ( in ) :: os_name !> Boolean value of whether os_name is valid or not logical , intent ( out ) :: is_valid select case ( os_name ) case ( \"linux\" , \"macos\" , \"windows\" , \"cygwin\" , \"solaris\" , \"freebsd\" , & & \"openbsd\" , \"unknown\" ) is_valid = . true . case default is_valid = . false . end select end subroutine validate_os_name","tags":"","loc":"proc/validate_os_name.html"},{"title":"validate_profile_table – Fortran-lang/fpm","text":"public subroutine validate_profile_table(profile_name, compiler_name, key_list, table, error, os_valid) Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: key_list (:) List of keys in the table type(toml_table), intent(in), pointer :: table Table containing OS tables type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in) :: os_valid Was called with valid operating system Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: c_flags character(len=:), public, allocatable :: cxx_flags character(len=:), public, allocatable :: err_message character(len=:), public, allocatable :: file_flags type(toml_key), public, allocatable :: file_list (:) character(len=:), public, allocatable :: file_name type(toml_table), public, pointer :: files character(len=:), public, allocatable :: flags integer, public :: ifile integer, public :: ikey logical, public :: is_valid character(len=:), public, allocatable :: key_name character(len=:), public, allocatable :: link_time_flags integer, public :: stat Source Code subroutine validate_profile_table ( profile_name , compiler_name , key_list , table , error , os_valid ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of keys in the table type ( toml_key ), allocatable , intent ( in ) :: key_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Was called with valid operating system logical , intent ( in ) :: os_valid character ( len = :), allocatable :: flags , c_flags , cxx_flags , link_time_flags , key_name , file_name , file_flags , err_message type ( toml_table ), pointer :: files type ( toml_key ), allocatable :: file_list (:) integer :: ikey , ifile , stat logical :: is_valid if ( size ( key_list ). ge . 1 ) then do ikey = 1 , size ( key_list ) key_name = key_list ( ikey )% key if ( key_name . eq . 'flags' ) then call get_value ( table , 'flags' , flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'c-flags' ) then call get_value ( table , 'c-flags' , c_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"c-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'cxx-flags' ) then call get_value ( table , 'cxx-flags' , cxx_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"cxx-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'link-time-flags' ) then call get_value ( table , 'link-time-flags' , link_time_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"link-time-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'files' ) then call get_value ( table , 'files' , files , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"files has to be a table\" ) return end if call files % get_keys ( file_list ) do ifile = 1 , size ( file_list ) file_name = file_list ( ifile )% key call get_value ( files , file_name , file_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"file scope flags has to be a key-value pair\" ) return end if end do else if (. not . os_valid ) then call validate_os_name ( key_name , is_valid ) err_message = \"Unexpected key \" // key_name // \" found in profile table \" // profile_name // \" \" // compiler_name // \".\" if (. not . is_valid ) call syntax_error ( error , err_message ) else err_message = \"Unexpected key \" // key_name // \" found in profile table \" // profile_name // \" \" // compiler_name // \".\" call syntax_error ( error , err_message ) end if end do end if if ( allocated ( error )) return end subroutine validate_profile_table","tags":"","loc":"proc/validate_profile_table.html"},{"title":"build_progress_t – Fortran-lang/fpm","text":"public interface build_progress_t Constructor for build_progress_t Module Procedures private function new_build_progress(target_queue, plain_mode) result(progress) Initialise a new build progress object Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in), target :: target_queue (:) The queue of scheduled targets logical, intent(in), optional :: plain_mode Enable ‘plain’ output for progress object Return Value type( build_progress_t ) Progress object to initialise","tags":"","loc":"interface/build_progress_t.html"},{"title":"FPM_TARGET_NAME – Fortran-lang/fpm","text":"public pure function FPM_TARGET_NAME(type) result(msg) Target type name Arguments Type Intent Optional Attributes Name integer, intent(in) :: type Return Value character(len=:), allocatable Source Code pure function FPM_TARGET_NAME ( type ) result ( msg ) integer , intent ( in ) :: type character (:), allocatable :: msg select case ( type ) case ( FPM_TARGET_ARCHIVE ); msg = 'Archive' case ( FPM_TARGET_CPP_OBJECT ); msg = 'C++ object' case ( FPM_TARGET_C_OBJECT ); msg = 'C Object' case ( FPM_TARGET_EXECUTABLE ); msg = 'Executable' case ( FPM_TARGET_OBJECT ); msg = 'Object' case default ; msg = 'Unknown' end select end function FPM_TARGET_NAME","tags":"","loc":"proc/fpm_target_name.html"},{"title":"add_dependency – Fortran-lang/fpm","text":"public subroutine add_dependency(target, dependency) Add pointer to dependeny in target%dependencies Arguments Type Intent Optional Attributes Name type( build_target_t ), intent(inout) :: target type( build_target_t ), intent(in), target :: dependency Source Code subroutine add_dependency ( target , dependency ) type ( build_target_t ), intent ( inout ) :: target type ( build_target_t ) , intent ( in ), target :: dependency target % dependencies = [ target % dependencies , build_target_ptr ( dependency )] end subroutine add_dependency","tags":"","loc":"proc/add_dependency.html"},{"title":"add_target – Fortran-lang/fpm","text":"public subroutine add_target(targets, package, type, output_name, source, link_libraries, features, preprocess, version) Allocate a new target and append to target list Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout), allocatable :: targets (:) character(len=*), intent(in) :: package integer, intent(in) :: type character(len=*), intent(in) :: output_name type( srcfile_t ), intent(in), optional :: source type( string_t ), intent(in), optional :: link_libraries (:) type( fortran_features_t ), intent(in), optional :: features type( preprocess_config_t ), intent(in), optional :: preprocess character(len=*), intent(in), optional :: version Source Code subroutine add_target ( targets , package , type , output_name , source , link_libraries , & & features , preprocess , version ) type ( build_target_ptr ), allocatable , intent ( inout ) :: targets (:) character ( * ), intent ( in ) :: package integer , intent ( in ) :: type character ( * ), intent ( in ) :: output_name type ( srcfile_t ), intent ( in ), optional :: source type ( string_t ), intent ( in ), optional :: link_libraries (:) type ( fortran_features_t ), intent ( in ), optional :: features type ( preprocess_config_t ), intent ( in ), optional :: preprocess character ( * ), intent ( in ), optional :: version integer :: i type ( build_target_t ), pointer :: new_target if (. not . allocated ( targets )) allocate ( targets ( 0 )) ! Check for duplicate outputs do i = 1 , size ( targets ) if ( targets ( i )% ptr % output_name == output_name ) then write ( * , * ) 'Error while building target list: duplicate output object \"' ,& output_name , '\"' if ( present ( source )) write ( * , * ) ' Source file: \"' , source % file_name , '\"' call fpm_stop ( 1 , ' ' ) end if end do allocate ( new_target ) new_target % target_type = type new_target % output_name = output_name new_target % package_name = package if ( present ( source )) new_target % source = source if ( present ( link_libraries )) new_target % link_libraries = link_libraries if ( present ( features )) new_target % features = features if ( present ( preprocess )) then if ( allocated ( preprocess % macros )) new_target % macros = preprocess % macros endif if ( present ( version )) new_target % version = version allocate ( new_target % dependencies ( 0 )) targets = [ targets , build_target_ptr ( new_target )] end subroutine add_target","tags":"","loc":"proc/add_target.html"},{"title":"filter_executable_targets – Fortran-lang/fpm","text":"public subroutine filter_executable_targets(targets, scope, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) integer, intent(in) :: scope type( string_t ), intent(out), allocatable :: list (:) Source Code subroutine filter_executable_targets ( targets , scope , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) integer , intent ( in ) :: scope type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , n n = 0 call resize ( list ) do i = 1 , size ( targets ) if ( is_executable_target ( targets ( i )% ptr , scope )) then if ( n >= size ( list )) call resize ( list ) n = n + 1 list ( n )% s = targets ( i )% ptr % output_file end if end do call resize ( list , n ) end subroutine filter_executable_targets","tags":"","loc":"proc/filter_executable_targets.html"},{"title":"filter_library_targets – Fortran-lang/fpm","text":"public subroutine filter_library_targets(targets, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) type( string_t ), intent(out), allocatable :: list (:) Source Code subroutine filter_library_targets ( targets , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , n n = 0 call resize ( list ) do i = 1 , size ( targets ) if ( targets ( i )% ptr % target_type == FPM_TARGET_ARCHIVE ) then if ( n >= size ( list )) call resize ( list ) n = n + 1 list ( n )% s = targets ( i )% ptr % output_file end if end do call resize ( list , n ) end subroutine filter_library_targets","tags":"","loc":"proc/filter_library_targets.html"},{"title":"filter_modules – Fortran-lang/fpm","text":"public subroutine filter_modules(targets, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) type( string_t ), intent(out), allocatable :: list (:) Source Code subroutine filter_modules ( targets , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , j , n n = 0 call resize ( list ) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if (. not . allocated ( target % source )) cycle if ( target % source % unit_type == FPM_UNIT_SUBMODULE ) cycle if ( n + size ( target % source % modules_provided ) >= size ( list )) call resize ( list ) do j = 1 , size ( target % source % modules_provided ) n = n + 1 list ( n )% s = join_path ( target % output_dir , & target % source % modules_provided ( j )% s ) end do end associate end do call resize ( list , n ) end subroutine filter_modules","tags":"","loc":"proc/filter_modules.html"},{"title":"resolve_module_dependencies – Fortran-lang/fpm","text":"public subroutine resolve_module_dependencies(targets, external_modules, error) Add dependencies to source-based targets ( FPM_TARGET_OBJECT )\n based on any modules used by the corresponding source file. Source file scoping Source files are assigned a scope of either FPM_SCOPE_LIB , FPM_SCOPE_APP or FPM_SCOPE_TEST . The scope controls which\n modules may be used by the source file: Library sources ( FPM_SCOPE_LIB ) may only use modules\n also with library scope. This includes library modules\n from dependencies. Executable sources ( FPM_SCOPE_APP , FPM_SCOPE_TEST ) may use\n library modules (including dependencies) as well as any modules\n corresponding to source files in the same directory or a\n subdirectory of the executable source file. @note Warning\n If a module used by a source file cannot be resolved to\n a source file in the package of the correct scope, then a fatal error is returned by the procedure and model construction fails. Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout), target :: targets (:) type( string_t ), intent(in) :: external_modules (:) type( error_t ), intent(out), allocatable :: error Source Code subroutine resolve_module_dependencies ( targets , external_modules , error ) type ( build_target_ptr ), intent ( inout ), target :: targets (:) type ( string_t ), intent ( in ) :: external_modules (:) type ( error_t ), allocatable , intent ( out ) :: error type ( build_target_ptr ) :: dep integer :: i , j do i = 1 , size ( targets ) if (. not . allocated ( targets ( i )% ptr % source )) cycle do j = 1 , size ( targets ( i )% ptr % source % modules_used ) if ( targets ( i )% ptr % source % modules_used ( j )% s . in . targets ( i )% ptr % source % modules_provided ) then ! Dependency satisfied in same file, skip cycle end if if ( targets ( i )% ptr % source % modules_used ( j )% s . in . external_modules ) then ! Dependency satisfied in system-installed module cycle end if if ( any ( targets ( i )% ptr % source % unit_scope == & [ FPM_SCOPE_APP , FPM_SCOPE_EXAMPLE , FPM_SCOPE_TEST ])) then dep % ptr => & find_module_dependency ( targets , targets ( i )% ptr % source % modules_used ( j )% s , & include_dir = dirname ( targets ( i )% ptr % source % file_name )) else dep % ptr => & find_module_dependency ( targets , targets ( i )% ptr % source % modules_used ( j )% s ) end if if (. not . associated ( dep % ptr )) then call fatal_error ( error , & 'Unable to find source for module dependency: \"' // & targets ( i )% ptr % source % modules_used ( j )% s // & '\" used by \"' // targets ( i )% ptr % source % file_name // '\"' ) return end if call add_dependency ( targets ( i )% ptr , dep % ptr ) end do end do end subroutine resolve_module_dependencies","tags":"","loc":"proc/resolve_module_dependencies.html"},{"title":"targets_from_sources – Fortran-lang/fpm","text":"public subroutine targets_from_sources(targets, model, prune, error) High-level wrapper to generate build target information Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(out), allocatable :: targets (:) The generated list of build targets type( fpm_model_t ), intent(inout), target :: model The package model from which to construct the target list logical, intent(in) :: prune Enable tree-shaking/pruning of module dependencies type( error_t ), intent(out), allocatable :: error Error structure Source Code subroutine targets_from_sources ( targets , model , prune , error ) !> The generated list of build targets type ( build_target_ptr ), intent ( out ), allocatable :: targets (:) !> The package model from which to construct the target list type ( fpm_model_t ), intent ( inout ), target :: model !> Enable tree-shaking/pruning of module dependencies logical , intent ( in ) :: prune !> Error structure type ( error_t ), intent ( out ), allocatable :: error call build_target_list ( targets , model ) call collect_exe_link_dependencies ( targets ) call resolve_module_dependencies ( targets , model % external_modules , error ) if ( allocated ( error )) return if ( prune ) then call prune_build_targets ( targets , root_package = model % package_name ) end if call resolve_target_linking ( targets , model ) end subroutine targets_from_sources","tags":"","loc":"proc/targets_from_sources.html"},{"title":"get_exe_name_with_suffix – Fortran-lang/fpm","text":"public function get_exe_name_with_suffix(source) result(suffixed) Build an executable name with suffix. Safe routine that always returns an allocated string Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(in) :: source Return Value character(len=:), allocatable Source Code function get_exe_name_with_suffix ( source ) result ( suffixed ) type ( srcfile_t ), intent ( in ) :: source character ( len = :), allocatable :: suffixed if ( allocated ( source % exe_name )) then if ( get_os_type () == OS_WINDOWS ) then suffixed = source % exe_name // '.exe' else suffixed = source % exe_name end if else suffixed = \"\" endif end function get_exe_name_with_suffix","tags":"","loc":"proc/get_exe_name_with_suffix.html"},{"title":"add_executable_sources – Fortran-lang/fpm","text":"public subroutine add_executable_sources(sources, executables, scope, auto_discover, with_f_ext, error) Add to sources using the executable and test entries in the manifest and\napplies any executable-specific overrides such as executable%name .\nAdds all sources (including modules) from each executable%source_dir Compare lowercase strings to allow auto-discovery of pre-processed extensions Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(inout), allocatable, target :: sources (:) List of [[srcfile_t]] objects to append to. Allocated if not allocated class( executable_config_t ), intent(in) :: executables (:) List of [[executable_config_t]] entries from manifest integer, intent(in) :: scope Scope to apply to the discovered sources: either FPM_SCOPE_APP or FPM_SCOPE_TEST , see fpm_model logical, intent(in) :: auto_discover If .false. only executables and tests specified in the manifest are added to sources type( string_t ), intent(in), optional :: with_f_ext (:) Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine add_executable_sources ( sources , executables , scope , auto_discover , with_f_ext , error ) !> List of `[[srcfile_t]]` objects to append to. Allocated if not allocated type ( srcfile_t ), allocatable , intent ( inout ), target :: sources (:) !> List of `[[executable_config_t]]` entries from manifest class ( executable_config_t ), intent ( in ) :: executables (:) !> Scope to apply to the discovered sources: either `FPM_SCOPE_APP` or `FPM_SCOPE_TEST`, see [[fpm_model]] integer , intent ( in ) :: scope !> If `.false.` only executables and tests specified in the manifest are added to `sources` logical , intent ( in ) :: auto_discover !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j type ( string_t ), allocatable :: exe_dirs (:) type ( srcfile_t ) :: exe_source call get_executable_source_dirs ( exe_dirs , executables ) do i = 1 , size ( exe_dirs ) call add_sources_from_dir ( sources , exe_dirs ( i )% s , scope , & with_executables = auto_discover , with_f_ext = with_f_ext , recurse = . false ., error = error ) if ( allocated ( error )) then return end if end do exe_loop : do i = 1 , size ( executables ) ! Check if executable already discovered automatically ! and apply any overrides do j = 1 , size ( sources ) !> Compare lowercase strings to allow auto-discovery of pre-processed extensions if ( lower ( basename ( sources ( j )% file_name , suffix = . true .)) == lower ( executables ( i )% main ) . and .& canon_path ( dirname ( sources ( j )% file_name )) == & canon_path ( executables ( i )% source_dir ) ) then sources ( j )% exe_name = executables ( i )% name if ( allocated ( executables ( i )% link )) then sources ( j )% link_libraries = executables ( i )% link end if sources ( j )% unit_type = FPM_UNIT_PROGRAM cycle exe_loop end if end do ! Add if not already discovered (auto_discovery off) associate ( exe => executables ( i )) exe_source = parse_source ( join_path ( exe % source_dir , exe % main ), with_f_ext , error ) exe_source % exe_name = exe % name if ( allocated ( exe % link )) then exe_source % link_libraries = exe % link end if exe_source % unit_type = FPM_UNIT_PROGRAM exe_source % unit_scope = scope end associate if ( allocated ( error )) return if (. not . allocated ( sources )) then sources = [ exe_source ] else sources = [ sources , exe_source ] end if end do exe_loop end subroutine add_executable_sources","tags":"","loc":"proc/add_executable_sources.html"},{"title":"add_sources_from_dir – Fortran-lang/fpm","text":"public subroutine add_sources_from_dir(sources, directory, scope, with_executables, with_f_ext, recurse, error) Add to sources by looking for source files in directory Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(inout), allocatable, target :: sources (:) List of [[srcfile_t]] objects to append to. Allocated if not allocated character(len=*), intent(in) :: directory Directory in which to search for source files integer, intent(in) :: scope Scope to apply to the discovered sources, see fpm_model for enumeration logical, intent(in), optional :: with_executables Executable sources (fortran program s) are ignored unless with_executables=.true. type( string_t ), intent(in), optional :: with_f_ext (:) Additional user-defined (preprocessor) extensions that should be treated as Fortran sources logical, intent(in), optional :: recurse Whether to recursively search subdirectories, default is .true. type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine add_sources_from_dir ( sources , directory , scope , with_executables , with_f_ext , recurse , error ) !> List of `[[srcfile_t]]` objects to append to. Allocated if not allocated type ( srcfile_t ), allocatable , intent ( inout ), target :: sources (:) !> Directory in which to search for source files character ( * ), intent ( in ) :: directory !> Scope to apply to the discovered sources, see [[fpm_model]] for enumeration integer , intent ( in ) :: scope !> Executable sources (fortran `program`s) are ignored unless `with_executables=.true.` logical , intent ( in ), optional :: with_executables !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) !> Whether to recursively search subdirectories, default is `.true.` logical , intent ( in ), optional :: recurse !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i logical , allocatable :: is_source (:), exclude_source (:) logical :: recurse_ type ( string_t ), allocatable :: file_names (:) type ( string_t ), allocatable :: src_file_names (:), f_ext (:) type ( string_t ), allocatable :: existing_src_files (:) type ( srcfile_t ), allocatable :: dir_sources (:) recurse_ = . true . if ( present ( recurse )) recurse_ = recurse ! Scan directory for sources call list_files ( directory , file_names , recurse = recurse_ ) if ( allocated ( sources )) then allocate ( existing_src_files ( size ( sources ))) do i = 1 , size ( sources ) existing_src_files ( i )% s = canon_path ( sources ( i )% file_name ) end do else allocate ( existing_src_files ( 0 )) end if ! Get legal fortran suffixes call list_fortran_suffixes ( f_ext , with_f_ext ) is_source = [(. not .( is_hidden_file ( basename ( file_names ( i )% s ))) . and . & . not .( canon_path ( file_names ( i )% s ) . in . existing_src_files ) . and . & ( str_ends_with ( lower ( file_names ( i )% s ), f_ext ) . or . & str_ends_with ( lower ( file_names ( i )% s ), c_suffixes ) ), i = 1 , size ( file_names ))] src_file_names = pack ( file_names , is_source ) allocate ( dir_sources ( size ( src_file_names ))) allocate ( exclude_source ( size ( src_file_names ))) do i = 1 , size ( src_file_names ) dir_sources ( i ) = parse_source ( src_file_names ( i )% s , with_f_ext , error ) if ( allocated ( error )) return dir_sources ( i )% unit_scope = scope allocate ( dir_sources ( i )% link_libraries ( 0 )) ! Exclude executables unless specified otherwise exclude_source ( i ) = ( dir_sources ( i )% unit_type == FPM_UNIT_PROGRAM ) if ( dir_sources ( i )% unit_type == FPM_UNIT_PROGRAM . and . & & present ( with_executables )) then if ( with_executables ) then exclude_source ( i ) = . false . end if end if end do if (. not . allocated ( sources )) then sources = pack ( dir_sources ,. not . exclude_source ) else sources = [ sources , pack ( dir_sources ,. not . exclude_source )] end if end subroutine add_sources_from_dir","tags":"","loc":"proc/add_sources_from_dir.html"},{"title":"get_fpm_env – Fortran-lang/fpm","text":"public function get_fpm_env(env, default) result(val) Get an environment variable for fpm, this routine ensures that every variable\nused by fpm is prefixed with FPM_. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: env character(len=*), intent(in) :: default Return Value character(len=:), allocatable Source Code function get_fpm_env ( env , default ) result ( val ) character ( len =* ), intent ( in ) :: env character ( len =* ), intent ( in ) :: default character ( len = :), allocatable :: val character ( len =* ), parameter :: fpm_prefix = \"FPM_\" val = get_env ( fpm_prefix // env , default ) end function get_fpm_env","tags":"","loc":"proc/get_fpm_env.html"},{"title":"get_command_line_settings – Fortran-lang/fpm","text":"public subroutine get_command_line_settings(cmd_settings) ! canon_path is not converting “.”, etc.\n& ‘ unknown help topic “’//trim(unnamed(i)).’not found in:’,manual] Arguments Type Intent Optional Attributes Name class( fpm_cmd_settings ), intent(out), allocatable :: cmd_settings Source Code subroutine get_command_line_settings ( cmd_settings ) class ( fpm_cmd_settings ), allocatable , intent ( out ) :: cmd_settings integer , parameter :: widest = 256 character ( len = 4096 ) :: cmdarg integer :: i integer :: os type ( fpm_install_settings ), allocatable :: install_settings type ( fpm_publish_settings ), allocatable :: publish_settings type ( fpm_export_settings ) , allocatable :: export_settings type ( version_t ) :: version character ( len = :), allocatable :: common_args , compiler_args , run_args , working_dir , & & c_compiler , cxx_compiler , archiver , version_s , token_s character ( len =* ), parameter :: fc_env = \"FC\" , cc_env = \"CC\" , ar_env = \"AR\" , & & fflags_env = \"FFLAGS\" , cflags_env = \"CFLAGS\" , cxxflags_env = \"CXXFLAGS\" , ldflags_env = \"LDFLAGS\" , & & fc_default = \"gfortran\" , cc_default = \" \" , ar_default = \" \" , flags_default = \" \" , & & cxx_env = \"CXX\" , cxx_default = \" \" type ( error_t ), allocatable :: error call set_help () os = get_os_type () ! text for --version switch, select case ( os ) case ( OS_LINUX ); os_type = \"OS Type: Linux\" case ( OS_MACOS ); os_type = \"OS Type: macOS\" case ( OS_WINDOWS ); os_type = \"OS Type: Windows\" case ( OS_CYGWIN ); os_type = \"OS Type: Cygwin\" case ( OS_SOLARIS ); os_type = \"OS Type: Solaris\" case ( OS_FREEBSD ); os_type = \"OS Type: FreeBSD\" case ( OS_OPENBSD ); os_type = \"OS Type: OpenBSD\" case ( OS_UNKNOWN ); os_type = \"OS Type: Unknown\" case default ; os_type = \"OS Type: UNKNOWN\" end select ! Get current release version version = fpm_version () version_s = version % s () version_text = [ character ( len = 80 ) :: & & 'Version: ' // trim ( version_s ) // ', alpha' , & & 'Program: fpm(1)' , & & 'Description: A Fortran package manager and build system' , & & 'Home Page: https://github.com/fortran-lang/fpm' , & & 'License: MIT' , & & os_type ] ! find the subcommand name by looking for first word on command ! not starting with dash CLI_RESPONSE_FILE = . true . cmdarg = get_subcommand () common_args = & ' --directory:C \" \"' // & ' --verbose F' run_args = & ' --target \" \"' // & ' --list F' // & ' --runner \" \"' // & ' --runner-args \" \"' compiler_args = & ' --profile \" \"' // & ' --no-prune F' // & ' --compiler \"' // get_fpm_env ( fc_env , fc_default ) // '\"' // & ' --c-compiler \"' // get_fpm_env ( cc_env , cc_default ) // '\"' // & ' --cxx-compiler \"' // get_fpm_env ( cxx_env , cxx_default ) // '\"' // & ' --archiver \"' // get_fpm_env ( ar_env , ar_default ) // '\"' // & ' --flag:: \"' // get_fpm_env ( fflags_env , flags_default ) // '\"' // & ' --c-flag:: \"' // get_fpm_env ( cflags_env , flags_default ) // '\"' // & ' --cxx-flag:: \"' // get_fpm_env ( cxxflags_env , flags_default ) // '\"' // & ' --link-flag:: \"' // get_fpm_env ( ldflags_env , flags_default ) // '\"' ! now set subcommand-specific help text and process commandline ! arguments. Then call subcommand routine select case ( trim ( cmdarg )) case ( 'run' ) call set_args ( common_args // compiler_args // run_args // '& & --all F & & --example F& & --' , help_run , version_text ) call check_build_vals () if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif if ( specified ( 'target' ) ) then call split ( sget ( 'target' ), tnames , delimiters = ' ,:' ) names = [ character ( len = max ( len ( names ), len ( tnames ))) :: names , tnames ] endif ! convert --all to '*' if ( lget ( 'all' )) then names = [ character ( len = max ( len ( names ), 1 )) :: names , '*' ] endif ! convert special string '..' to equivalent (shorter) '*' ! to allow for a string that does not require shift-key and quoting do i = 1 , size ( names ) if ( names ( i ) == '..' ) names ( i ) = '*' enddo ! If there are additional command-line arguments, remove the additional ! double quotes which have been added by M_CLI2 val_runner_args = sget ( 'runner-args' ) call remove_characters_in_set ( val_runner_args , set = '\"' ) c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( fpm_run_settings :: cmd_settings ) val_runner = sget ( 'runner' ) if ( specified ( 'runner' ) . and . val_runner == '' ) val_runner = 'echo' cmd_settings = fpm_run_settings (& & args = remaining ,& & profile = val_profile ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & example = lget ( 'example' ), & & list = lget ( 'list' ),& & build_tests = . false .,& & name = names ,& & runner = val_runner ,& & runner_args = val_runner_args , & & verbose = lget ( 'verbose' ) ) case ( 'build' ) call set_args ( common_args // compiler_args // '& & --list F & & --show-model F & & --dump \" \" & & --tests F & & --' , help_build , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) val_dump = sget ( 'dump' ) if ( specified ( 'dump' ) . and . val_dump == '' ) val_dump = 'fpm_model.toml' allocate ( fpm_build_settings :: cmd_settings ) cmd_settings = fpm_build_settings ( & & profile = val_profile ,& & dump = val_dump ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & list = lget ( 'list' ),& & show_model = lget ( 'show-model' ),& & build_tests = lget ( 'tests' ),& & verbose = lget ( 'verbose' ) ) case ( 'new' ) call set_args ( common_args // '& & --src F & & --lib F & & --app F & & --test F & & --example F & & --backfill F & & --full F & & --bare F' , & & help_new , version_text ) select case ( size ( unnamed )) case ( 1 ) if ( lget ( 'backfill' )) then name = '.' else write ( stderr , '(*(7x,g0,/))' ) & & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]|[--full|--bare] [--backfill]' call fpm_stop ( 1 , 'directory name required' ) endif case ( 2 ) name = trim ( unnamed ( 2 )) case default write ( stderr , '(7x,g0)' ) & & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]| [--full|--bare] [--backfill]' call fpm_stop ( 2 , 'only one directory name allowed' ) end select !*! canon_path is not converting \".\", etc. if ( name == '.' ) then call get_current_directory ( name , error ) if ( allocated ( error )) then write ( stderr , '(\"[Error]\", 1x, a)' ) error % message stop 1 endif endif name = canon_path ( name ) if ( . not . is_fortran_name ( to_fortran_name ( basename ( name ))) ) then write ( stderr , '(g0)' ) [ character ( len = 72 ) :: & & ' the fpm project name must be made of up to 63 ASCII letters,' , & & ' numbers, underscores, or hyphens, and start with a letter.' ] call fpm_stop ( 4 , ' ' ) endif allocate ( fpm_new_settings :: cmd_settings ) if ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' , 'bare' ])) & & . and . lget ( 'full' ) ) then write ( stderr , '(*(a))' )& & ' --full and any of [--src|--lib,--app,--test,--example,--bare]' , & & ' are mutually exclusive.' call fpm_stop ( 5 , ' ' ) elseif ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' , 'full' ])) & & . and . lget ( 'bare' ) ) then write ( stderr , '(*(a))' )& & ' --bare and any of [--src|--lib,--app,--test,--example,--full]' , & & ' are mutually exclusive.' call fpm_stop ( 3 , ' ' ) elseif ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' ]) ) ) then cmd_settings = fpm_new_settings (& & backfill = lget ( 'backfill' ), & & name = name , & & with_executable = lget ( 'app' ), & & with_lib = any ([ lget ( 'lib' ), lget ( 'src' )]), & & with_test = lget ( 'test' ), & & with_example = lget ( 'example' ), & & verbose = lget ( 'verbose' ) ) else ! default if no specific directories are requested cmd_settings = fpm_new_settings (& & backfill = lget ( 'backfill' ) , & & name = name , & & with_executable = . true ., & & with_lib = . true ., & & with_test = . true ., & & with_example = lget ( 'full' ), & & with_full = lget ( 'full' ), & & with_bare = lget ( 'bare' ), & & verbose = lget ( 'verbose' ) ) endif case ( 'help' , 'manual' ) call set_args ( common_args , help_help , version_text ) if ( size ( unnamed ) < 2 ) then if ( unnamed ( 1 ) == 'help' ) then unnamed = [ ' ' , 'fpm' ] else unnamed = manual endif elseif ( unnamed ( 2 ) == 'manual' ) then unnamed = manual endif allocate ( character ( len = widest ) :: help_text ( 0 )) do i = 2 , size ( unnamed ) select case ( unnamed ( i )) case ( ' ' ) case ( 'fpm ' ) help_text = [ character ( len = widest ) :: help_text , help_fpm ] case ( 'new ' ) help_text = [ character ( len = widest ) :: help_text , help_new ] case ( 'build ' ) help_text = [ character ( len = widest ) :: help_text , help_build ] case ( 'install' ) help_text = [ character ( len = widest ) :: help_text , help_install ] case ( 'run ' ) help_text = [ character ( len = widest ) :: help_text , help_run ] case ( 'test ' ) help_text = [ character ( len = widest ) :: help_text , help_test ] case ( 'runner' ) help_text = [ character ( len = widest ) :: help_text , help_runner ] case ( 'list ' ) help_text = [ character ( len = widest ) :: help_text , help_list ] case ( 'update ' ) help_text = [ character ( len = widest ) :: help_text , help_update ] case ( 'help ' ) help_text = [ character ( len = widest ) :: help_text , help_help ] case ( 'version' ) help_text = [ character ( len = widest ) :: help_text , version_text ] case ( 'clean' ) help_text = [ character ( len = widest ) :: help_text , help_clean ] case ( 'publish' ) help_text = [ character ( len = widest ) :: help_text , help_publish ] case default help_text = [ character ( len = widest ) :: help_text , & & ' unknown help topic \"' // trim ( unnamed ( i )) // '\"' ] !!& ' unknown help topic \"'//trim(unnamed(i)).'not found in:',manual] end select enddo call printhelp ( help_text ) case ( 'install' ) call set_args ( common_args // compiler_args // '& & --no-rebuild F --prefix \" \" & & --list F & & --libdir \"lib\" --bindir \"bin\" --includedir \"include\"' , & help_install , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( install_settings , source = fpm_install_settings (& list = lget ( 'list' ), & profile = val_profile ,& prune = . not . lget ( 'no-prune' ), & compiler = val_compiler , & c_compiler = c_compiler , & cxx_compiler = cxx_compiler , & archiver = archiver , & flag = val_flag , & cflag = val_cflag , & cxxflag = val_cxxflag , & ldflag = val_ldflag , & no_rebuild = lget ( 'no-rebuild' ), & verbose = lget ( 'verbose' ))) call get_char_arg ( install_settings % prefix , 'prefix' ) call get_char_arg ( install_settings % libdir , 'libdir' ) call get_char_arg ( install_settings % bindir , 'bindir' ) call get_char_arg ( install_settings % includedir , 'includedir' ) call move_alloc ( install_settings , cmd_settings ) case ( 'list' ) call set_args ( common_args // '& & --list F& &' , help_list , version_text ) if ( lget ( 'list' )) then help_text = [ character ( widest ) :: help_list_nodash , help_list_dash ] else help_text = help_list_nodash endif call printhelp ( help_text ) case ( 'test' ) call set_args ( common_args // compiler_args // run_args // ' --' , & help_test , version_text ) call check_build_vals () if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif if ( specified ( 'target' ) ) then call split ( sget ( 'target' ), tnames , delimiters = ' ,:' ) names = [ character ( len = max ( len ( names ), len ( tnames ))) :: names , tnames ] endif ! convert special string '..' to equivalent (shorter) '*' ! to allow for a string that does not require shift-key and quoting do i = 1 , size ( names ) if ( names ( i ) == '..' ) names ( i ) = '*' enddo ! If there are additional command-line arguments, remove the additional ! double quotes which have been added by M_CLI2 val_runner_args = sget ( 'runner-args' ) call remove_characters_in_set ( val_runner_args , set = '\"' ) c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( fpm_test_settings :: cmd_settings ) val_runner = sget ( 'runner' ) if ( specified ( 'runner' ) . and . val_runner == '' ) val_runner = 'echo' cmd_settings = fpm_test_settings (& & args = remaining , & & profile = val_profile , & & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & example = . false ., & & list = lget ( 'list' ), & & build_tests = . true ., & & name = names , & & runner = val_runner , & & runner_args = val_runner_args , & & verbose = lget ( 'verbose' )) case ( 'update' ) call set_args ( common_args // ' --fetch-only F --clean F --dump \" \" ' , & help_update , version_text ) if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif val_dump = sget ( 'dump' ) if ( specified ( 'dump' ) . and . val_dump == '' ) val_dump = 'fpm_dependencies.toml' allocate ( fpm_update_settings :: cmd_settings ) cmd_settings = fpm_update_settings ( name = names , dump = val_dump , & fetch_only = lget ( 'fetch-only' ), verbose = lget ( 'verbose' ), & clean = lget ( 'clean' )) case ( 'export' ) call set_args ( common_args // compiler_args // '& & --manifest \"filename\" & & --model \"filename\" & & --dependencies \"filename\" ' , & help_build , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( export_settings , source = fpm_export_settings (& profile = val_profile ,& prune = . not . lget ( 'no-prune' ), & compiler = val_compiler , & c_compiler = c_compiler , & cxx_compiler = cxx_compiler , & archiver = archiver , & flag = val_flag , & cflag = val_cflag , & show_model = . true ., & cxxflag = val_cxxflag , & ldflag = val_ldflag , & verbose = lget ( 'verbose' ))) call get_char_arg ( export_settings % dump_model , 'model' ) call get_char_arg ( export_settings % dump_manifest , 'manifest' ) call get_char_arg ( export_settings % dump_dependencies , 'dependencies' ) call move_alloc ( export_settings , cmd_settings ) case ( 'clean' ) call set_args ( common_args // & & ' --registry-cache' // & & ' --skip' // & & ' --all' , & help_clean , version_text ) block logical :: skip , clean_all skip = lget ( 'skip' ) clean_all = lget ( 'all' ) if ( all ([ skip , clean_all ])) then call fpm_stop ( 6 , 'Do not specify both --skip and --all options on the clean subcommand.' ) end if allocate ( fpm_clean_settings :: cmd_settings ) cmd_settings = fpm_clean_settings ( & & registry_cache = lget ( 'registry-cache' ), & & clean_skip = skip , & & clean_all = clean_all ) end block case ( 'publish' ) call set_args ( common_args // compiler_args // '& & --show-package-version F & & --show-upload-data F & & --dry-run F & & --token \" \" & & --list F & & --show-model F & & --tests F & & --' , help_publish , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) token_s = sget ( 'token' ) allocate ( fpm_publish_settings :: cmd_settings ) cmd_settings = fpm_publish_settings ( & & show_package_version = lget ( 'show-package-version' ), & & show_upload_data = lget ( 'show-upload-data' ), & & is_dry_run = lget ( 'dry-run' ), & & profile = val_profile ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & list = lget ( 'list' ),& & show_model = lget ( 'show-model' ),& & build_tests = lget ( 'tests' ),& & verbose = lget ( 'verbose' ),& & token = token_s ) case default if ( cmdarg . ne . '' . and . which ( 'fpm-' // cmdarg ). ne . '' ) then call run ( 'fpm-' // trim ( cmdarg ) // ' ' // get_command_arguments_quoted (),. false .) stop else call set_args ( '& & --list F& &' , help_fpm , version_text ) ! Note: will not get here if --version or --usage or --help ! is present on commandline if ( lget ( 'list' )) then help_text = help_list_dash elseif ( len_trim ( cmdarg ) == 0 ) then write ( stdout , '(*(a))' ) 'Fortran Package Manager:' write ( stdout , '(*(a))' ) ' ' help_text = [ character ( widest ) :: help_list_nodash , help_usage ] else write ( stderr , '(*(a))' ) ' unknown subcommand [' , & & trim ( cmdarg ), ']' help_text = [ character ( widest ) :: help_list_dash , help_usage ] endif call printhelp ( help_text ) endif end select if ( allocated ( cmd_settings )) then working_dir = sget ( \"directory\" ) call move_alloc ( working_dir , cmd_settings % working_dir ) end if contains subroutine check_build_vals () val_compiler = sget ( 'compiler' ) if ( val_compiler == '' ) val_compiler = 'gfortran' val_flag = \" \" // sget ( 'flag' ) val_cflag = \" \" // sget ( 'c-flag' ) val_cxxflag = \" \" // sget ( 'cxx-flag' ) val_ldflag = \" \" // sget ( 'link-flag' ) val_profile = sget ( 'profile' ) end subroutine check_build_vals !> Print help text and stop subroutine printhelp ( lines ) character ( len = :), intent ( in ), allocatable :: lines (:) integer :: iii , ii if ( allocated ( lines )) then ii = size ( lines ) if ( ii > 0 . and . len ( lines ) > 0 ) then write ( stdout , '(g0)' )( trim ( lines ( iii )), iii = 1 , ii ) else write ( stdout , '(a)' ) ' *printhelp* output requested is empty' endif endif stop end subroutine printhelp end subroutine get_command_line_settings","tags":"","loc":"proc/get_command_line_settings.html"},{"title":"cmd_update – Fortran-lang/fpm","text":"public subroutine cmd_update(settings) Entry point for the update subcommand Arguments Type Intent Optional Attributes Name type( fpm_update_settings ), intent(in) :: settings Representation of the command line arguments Source Code subroutine cmd_update ( settings ) !> Representation of the command line arguments type ( fpm_update_settings ), intent ( in ) :: settings type ( package_config_t ) :: package type ( dependency_tree_t ) :: deps type ( error_t ), allocatable :: error integer :: ii character ( len = :), allocatable :: cache call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) if (. not . exists ( \"build\" )) then call mkdir ( \"build\" ) call filewrite ( join_path ( \"build\" , \".gitignore\" ),[ \"*\" ]) end if cache = join_path ( \"build\" , \"cache.toml\" ) if ( settings % clean ) call delete_file ( cache ) call new_dependency_tree ( deps , cache = cache , & verbosity = merge ( 2 , 1 , settings % verbose )) call deps % add ( package , error ) call handle_error ( error ) ! Force-update all dependencies if `--clean` if ( settings % clean ) then do ii = 1 , deps % ndep deps % dep ( ii )% update = . true . end do end if if ( settings % fetch_only ) return if ( size ( settings % name ) == 0 ) then call deps % update ( error ) call handle_error ( error ) else do ii = 1 , size ( settings % name ) call deps % update ( trim ( settings % name ( ii )), error ) call handle_error ( error ) end do end if if ( len_trim ( settings % dump ) > 0 ) then call deps % dump ( trim ( settings % dump ), error , json = name_is_json ( trim ( settings % dump ))) call handle_error ( error ) end if end subroutine cmd_update","tags":"","loc":"proc/cmd_update.html"},{"title":"cmd_export – Fortran-lang/fpm","text":"public subroutine cmd_export(settings) Entry point for the export subcommand\nRead in manifest\nExport manifest\nExport dependency tree Generate dependency tree\nExport dependency tree\nExport full model Arguments Type Intent Optional Attributes Name type( fpm_export_settings ), intent(inout) :: settings Representation of the command line arguments Source Code subroutine cmd_export ( settings ) !> Representation of the command line arguments type ( fpm_export_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( dependency_tree_t ) :: deps type ( fpm_model_t ) :: model type ( error_t ), allocatable :: error integer :: ii character ( len = :), allocatable :: filename if ( len_trim ( settings % dump_manifest ) <= 0 . and . & len_trim ( settings % dump_model ) <= 0 . and . & len_trim ( settings % dump_dependencies ) <= 0 ) then call fpm_stop ( 0 , '*cmd_export* exiting: no manifest/model/dependencies keyword provided' ) end if !> Read in manifest call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) !> Export manifest if ( len_trim ( settings % dump_manifest ) > 0 ) then filename = trim ( settings % dump_manifest ) call package % dump ( filename , error , json = name_is_json ( filename )) end if !> Export dependency tree if ( len_trim ( settings % dump_dependencies ) > 0 ) then !> Generate dependency tree filename = join_path ( \"build\" , \"cache.toml\" ) call new_dependency_tree ( deps , cache = filename , verbosity = merge ( 2 , 1 , settings % verbose )) call deps % add ( package , error ) call handle_error ( error ) !> Export dependency tree filename = settings % dump_dependencies call deps % dump ( filename , error , json = name_is_json ( filename )) call handle_error ( error ) end if !> Export full model if ( len_trim ( settings % dump_model ) > 0 ) then call build_model ( model , settings % fpm_build_settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_export* Model error: ' // error % message ) end if filename = settings % dump_model call model % dump ( filename , error , json = name_is_json ( filename )) call handle_error ( error ) end if end subroutine cmd_export","tags":"","loc":"proc/cmd_export.html"},{"title":"check_and_read_pkg_data – Fortran-lang/fpm","text":"public subroutine check_and_read_pkg_data(json, node, download_url, version, error) Arguments Type Intent Optional Attributes Name type(json_object), intent(inout) :: json class( dependency_node_t ), intent(in) :: node character(len=:), intent(out), allocatable :: download_url type( version_t ), intent(out) :: version type( error_t ), intent(out), allocatable :: error","tags":"","loc":"proc/check_and_read_pkg_data.html"},{"title":"destroy_dependency_node – Fortran-lang/fpm","text":"public elemental subroutine destroy_dependency_node(self) Destructor Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self Source Code elemental subroutine destroy_dependency_node ( self ) class ( dependency_node_t ), intent ( inout ) :: self integer :: ierr call dependency_destroy ( self ) deallocate ( self % version , stat = ierr ) deallocate ( self % proj_dir , stat = ierr ) deallocate ( self % revision , stat = ierr ) self % done = . false . self % update = . false . self % cached = . false . end subroutine destroy_dependency_node","tags":"","loc":"proc/destroy_dependency_node.html"},{"title":"new_dependency_node – Fortran-lang/fpm","text":"public subroutine new_dependency_node(self, dependency, version, proj_dir, update) Create a new dependency node from a configuration Arguments Type Intent Optional Attributes Name type( dependency_node_t ), intent(out) :: self Instance of the dependency node type( dependency_config_t ), intent(in) :: dependency Dependency configuration data type( version_t ), intent(in), optional :: version Version of the dependency character(len=*), intent(in), optional :: proj_dir Installation prefix of the dependency logical, intent(in), optional :: update Dependency should be updated Source Code subroutine new_dependency_node ( self , dependency , version , proj_dir , update ) !> Instance of the dependency node type ( dependency_node_t ), intent ( out ) :: self !> Dependency configuration data type ( dependency_config_t ), intent ( in ) :: dependency !> Version of the dependency type ( version_t ), intent ( in ), optional :: version !> Installation prefix of the dependency character ( len =* ), intent ( in ), optional :: proj_dir !> Dependency should be updated logical , intent ( in ), optional :: update self % dependency_config_t = dependency if ( present ( version )) then self % version = version end if if ( present ( proj_dir )) then self % proj_dir = proj_dir end if if ( present ( update )) then self % update = update end if end subroutine new_dependency_node","tags":"","loc":"proc/new_dependency_node.html"},{"title":"new_dependency_tree – Fortran-lang/fpm","text":"public subroutine new_dependency_tree(self, verbosity, cache) Create a new dependency tree Arguments Type Intent Optional Attributes Name type( dependency_tree_t ), intent(out) :: self Instance of the dependency tree integer, intent(in), optional :: verbosity Verbosity of printout character(len=*), intent(in), optional :: cache Name of the cache file Source Code subroutine new_dependency_tree ( self , verbosity , cache ) !> Instance of the dependency tree type ( dependency_tree_t ), intent ( out ) :: self !> Verbosity of printout integer , intent ( in ), optional :: verbosity !> Name of the cache file character ( len =* ), intent ( in ), optional :: cache call resize ( self % dep ) self % dep_dir = join_path ( \"build\" , \"dependencies\" ) if ( present ( verbosity )) self % verbosity = verbosity if ( present ( cache )) self % cache = cache end subroutine new_dependency_tree","tags":"","loc":"proc/new_dependency_tree.html"},{"title":"resize – Fortran-lang/fpm","text":"public interface resize Overloaded reallocation interface Module Procedures private pure subroutine resize_dependency_node(var, n) Reallocate a list of dependencies Arguments Type Intent Optional Attributes Name type( dependency_node_t ), intent(inout), allocatable :: var (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size","tags":"","loc":"interface/resize~2.html"},{"title":"assert_pkg_config – Fortran-lang/fpm","text":"public function assert_pkg_config() Check whether pkg-config is available on the local system Arguments None Return Value logical Source Code logical function assert_pkg_config () integer :: exitcode logical :: success type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), args = [ string_t ( '-h' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) assert_pkg_config = exitcode == 0 . and . success end function assert_pkg_config","tags":"","loc":"proc/assert_pkg_config.html"},{"title":"pkgcfg_get_build_flags – Fortran-lang/fpm","text":"public function pkgcfg_get_build_flags(name, allow_system, error) result(flags) Get build flags (option to include flags from system directories, that \ngfortran does not look into by default) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Package name logical, intent(in) :: allow_system Should pkg-config look in system paths? This is necessary for gfortran \nthat doesn’t otherwise look into them type( error_t ), intent(out), allocatable :: error Error flag Return Value type( string_t ), allocatable, (:) List of compile flags Source Code function pkgcfg_get_build_flags ( name , allow_system , error ) result ( flags ) !> Package name character ( * ), intent ( in ) :: name !> Should pkg-config look in system paths? This is necessary for gfortran !> that doesn't otherwise look into them logical , intent ( in ) :: allow_system !> Error flag type ( error_t ), allocatable , intent ( out ) :: error !> List of compile flags type ( string_t ), allocatable :: flags (:) integer :: exitcode , i , nlib logical :: old_had , success , old_allow character (:), allocatable :: old , tokens (:) type ( string_t ) :: log ! Check if the current environment includes system flags old = get_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , default = 'ERROR' ) old_had = old /= 'ERROR' old_allow = merge ( old == '1' ,. false ., old_had ) ! Set system flags success = set_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , value = merge ( '1' , '0' , allow_system )) if (. not . success ) then call fatal_error ( error , 'Cannot get pkg-config build flags: environment variable error.' ) return end if ! Now run wrapper call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( name ), string_t ( '--cflags' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) ! Split all arguments tokens = shlex_split ( log % s ) nlib = size ( tokens ) allocate ( flags ( nlib )) do i = 1 , nlib flags ( i ) = string_t ( trim ( adjustl ( tokens ( i )))) end do else allocate ( flags ( 0 )) call fatal_error ( error , 'cannot get <' // name // '> build flags from pkg-config' ) end if ! Restore environment variable if ( old_had ) then success = set_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , value = old ) else success = delete_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' ) end if if (. not . success ) then call fatal_error ( error , 'Cannot get pkg-config build flags: environment variable error.' ) return end if end function pkgcfg_get_build_flags","tags":"","loc":"proc/pkgcfg_get_build_flags.html"},{"title":"pkgcfg_get_libs – Fortran-lang/fpm","text":"public function pkgcfg_get_libs(package, error) result(libraries) Get package libraries from pkg-config Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: package Package name type( error_t ), intent(out), allocatable :: error Error handler Return Value type( string_t ), allocatable, (:) A list of libraries Source Code function pkgcfg_get_libs ( package , error ) result ( libraries ) !> Package name character ( * ), intent ( in ) :: package !> Error handler type ( error_t ), allocatable , intent ( out ) :: error !> A list of libraries type ( string_t ), allocatable :: libraries (:) integer :: exitcode , nlib , i logical :: success character ( len = :), allocatable :: tokens (:) type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( package ), string_t ( '--libs' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) ! Split all arguments tokens = shlex_split ( log % s ) nlib = size ( tokens ) allocate ( libraries ( nlib )) do i = 1 , nlib libraries ( i ) = string_t ( trim ( adjustl ( tokens ( i )))) end do else allocate ( libraries ( 0 )) call fatal_error ( error , 'cannot get <' // package // '> libraries from pkg-config' ) end if end function pkgcfg_get_libs","tags":"","loc":"proc/pkgcfg_get_libs.html"},{"title":"pkgcfg_get_version – Fortran-lang/fpm","text":"public function pkgcfg_get_version(package, error) result(screen) Get package version from pkg-config Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: package Package name type( error_t ), intent(out), allocatable :: error Error handler Return Value type( string_t ) Source Code type ( string_t ) function pkgcfg_get_version ( package , error ) result ( screen ) !> Package name character ( * ), intent ( in ) :: package !> Error handler type ( error_t ), allocatable , intent ( out ) :: error integer :: exitcode logical :: success type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( package ), string_t ( '--modversion' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) screen = log else screen = string_t ( \"\" ) end if end function pkgcfg_get_version","tags":"","loc":"proc/pkgcfg_get_version.html"},{"title":"pkgcfg_has_package – Fortran-lang/fpm","text":"public function pkgcfg_has_package(name) result(success) Check if pkgcfg has package pkg-config –exists returns 0 only if the package exists Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Package name Return Value logical Source Code logical function pkgcfg_has_package ( name ) result ( success ) !> Package name character ( * ), intent ( in ) :: name integer :: exitcode logical :: cmdok type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( name ), string_t ( '--exists' )], & exitcode = exitcode , cmd_success = cmdok , screen_output = log ) !> pkg-config --exists returns 0 only if the package exists success = cmdok . and . exitcode == 0 end function pkgcfg_has_package","tags":"","loc":"proc/pkgcfg_has_package.html"},{"title":"pkgcfg_list_all – Fortran-lang/fpm","text":"public function pkgcfg_list_all(error, descriptions) result(modules) Return whole list of available pkg-cfg packages Extract list Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Error handler type( string_t ), intent(out), optional, allocatable :: descriptions (:) An optional list of package descriptions Return Value type( string_t ), allocatable, (:) A list of all available packages Source Code function pkgcfg_list_all ( error , descriptions ) result ( modules ) !> Error handler type ( error_t ), allocatable , intent ( out ) :: error !> A list of all available packages type ( string_t ), allocatable :: modules (:) !> An optional list of package descriptions type ( string_t ), optional , allocatable , intent ( out ) :: descriptions (:) integer :: exitcode , i , spc logical :: success character ( len = :), allocatable :: lines (:) type ( string_t ) :: log type ( string_t ), allocatable :: mods (:), descr (:) character ( * ), parameter :: CRLF = achar ( 13 ) // new_line ( 'a' ) call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( '--list-all' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if (. not .( success . and . exitcode == 0 )) then call fatal_error ( error , 'cannot get pkg-config modules' ) allocate ( modules ( 0 )) return end if !> Extract list call split ( log % s , lines , CRLF ) allocate ( mods ( size ( lines )), descr ( size ( lines ))) do i = 1 , size ( lines ) ! Module names have no spaces spc = index ( lines ( i ), ' ' ) if ( spc > 0 ) then mods ( i ) = string_t ( trim ( adjustl ( lines ( i )( 1 : spc )))) descr ( i ) = string_t ( trim ( adjustl ( lines ( i )( spc + 1 :)))) else mods ( i ) = string_t ( trim ( adjustl ( lines ( i )))) descr ( i ) = string_t ( \"\" ) end if end do call move_alloc ( from = mods , to = modules ) if ( present ( descriptions )) call move_alloc ( from = descr , to = descriptions ) end function pkgcfg_list_all","tags":"","loc":"proc/pkgcfg_list_all.html"},{"title":"run_wrapper – Fortran-lang/fpm","text":"public subroutine run_wrapper(wrapper, args, verbose, exitcode, cmd_success, screen_output) Simple call to execute_command_line involving one mpi* wrapper Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: wrapper type( string_t ), intent(in), optional :: args (:) logical, intent(in), optional :: verbose integer, intent(out), optional :: exitcode logical, intent(out), optional :: cmd_success type( string_t ), intent(out), optional :: screen_output Source Code subroutine run_wrapper ( wrapper , args , verbose , exitcode , cmd_success , screen_output ) type ( string_t ), intent ( in ) :: wrapper type ( string_t ), intent ( in ), optional :: args (:) logical , intent ( in ), optional :: verbose integer , intent ( out ), optional :: exitcode logical , intent ( out ), optional :: cmd_success type ( string_t ), intent ( out ), optional :: screen_output logical :: echo_local character (:), allocatable :: redirect_str , command , redirect , line integer :: iunit , iarg , stat , cmdstat if ( present ( verbose )) then echo_local = verbose else echo_local = . false . end if ! No redirection and non-verbose output if ( present ( screen_output )) then redirect = get_temp_filename () redirect_str = \">\" // redirect // \" 2>&1\" else if ( os_is_unix ()) then redirect_str = \" >/dev/null 2>&1\" else redirect_str = \" >NUL 2>&1\" end if end if ! Empty command if ( len_trim ( wrapper ) <= 0 ) then if ( echo_local ) print * , '+ ' if ( present ( exitcode )) exitcode = 0 if ( present ( cmd_success )) cmd_success = . true . if ( present ( screen_output )) screen_output = string_t ( \"\" ) return end if ! Init command command = trim ( wrapper % s ) add_arguments : if ( present ( args )) then do iarg = 1 , size ( args ) if ( len_trim ( args ( iarg )) <= 0 ) cycle command = trim ( command ) // ' ' // args ( iarg )% s end do endif add_arguments if ( echo_local ) print * , '+ ' , command ! Test command call execute_command_line ( command // redirect_str , exitstat = stat , cmdstat = cmdstat ) ! Command successful? if ( present ( cmd_success )) cmd_success = cmdstat == 0 ! Program exit code? if ( present ( exitcode )) exitcode = stat ! Want screen output? if ( present ( screen_output ) . and . cmdstat == 0 ) then allocate ( character ( len = 0 ) :: screen_output % s ) open ( newunit = iunit , file = redirect , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit screen_output % s = screen_output % s // new_line ( 'a' ) // line if ( echo_local ) write ( * , '(A)' ) trim ( line ) end do ! Close and delete file close ( iunit , status = 'delete' ) else call fpm_stop ( 1 , 'cannot read temporary file from successful MPI wrapper' ) endif end if end subroutine run_wrapper","tags":"","loc":"proc/run_wrapper.html"},{"title":"new_preprocess_config – Fortran-lang/fpm","text":"public subroutine new_preprocess_config(self, table, error) Construct a new preprocess configuration from TOML data structure Arguments Type Intent Optional Attributes Name type( preprocess_config_t ), intent(out) :: self Instance of the preprocess configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure. type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_preprocess_config ( self , table , error ) !> Instance of the preprocess configuration type ( preprocess_config_t ), intent ( out ) :: self !> Instance of the TOML data structure. type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call table % get_key ( self % name ) call get_list ( table , \"suffixes\" , self % suffixes , error ) if ( allocated ( error )) return call get_list ( table , \"directories\" , self % directories , error ) if ( allocated ( error )) return call get_list ( table , \"macros\" , self % macros , error ) if ( allocated ( error )) return end subroutine new_preprocess_config","tags":"","loc":"proc/new_preprocess_config.html"},{"title":"new_preprocessors – Fortran-lang/fpm","text":"public subroutine new_preprocessors(preprocessors, table, error) Construct new preprocess array from a TOML data structure. Arguments Type Intent Optional Attributes Name type( preprocess_config_t ), intent(out), allocatable :: preprocessors (:) Instance of the preprocess configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_preprocessors ( preprocessors , table , error ) !> Instance of the preprocess configuration type ( preprocess_config_t ), allocatable , intent ( out ) :: preprocessors (:) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: node type ( toml_key ), allocatable :: list (:) integer :: iprep , stat call table % get_keys ( list ) ! An empty table is not allowed if ( size ( list ) == 0 ) then call syntax_error ( error , \"No preprocessors defined\" ) end if allocate ( preprocessors ( size ( list ))) do iprep = 1 , size ( list ) call get_value ( table , list ( iprep )% key , node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Preprocessor \" // list ( iprep )% key // \" must be a table entry\" ) exit end if call new_preprocess_config ( preprocessors ( iprep ), node , error ) if ( allocated ( error )) exit end do end subroutine new_preprocessors","tags":"","loc":"proc/new_preprocessors.html"},{"title":"FPM_SCOPE_NAME – Fortran-lang/fpm","text":"public function FPM_SCOPE_NAME(flag) result(name) Return the character name of a scope flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: flag Return Value character(len=:), allocatable Source Code function FPM_SCOPE_NAME ( flag ) result ( name ) integer , intent ( in ) :: flag character ( len = :), allocatable :: name select case ( flag ) case ( FPM_SCOPE_UNKNOWN ); name = \"FPM_SCOPE_UNKNOWN\" case ( FPM_SCOPE_LIB ); name = \"FPM_SCOPE_LIB\" case ( FPM_SCOPE_DEP ); name = \"FPM_SCOPE_DEP\" case ( FPM_SCOPE_APP ); name = \"FPM_SCOPE_APP\" case ( FPM_SCOPE_TEST ); name = \"FPM_SCOPE_TEST\" case ( FPM_SCOPE_EXAMPLE ); name = \"FPM_SCOPE_EXAMPLE\" case default ; name = \"INVALID\" end select end function FPM_SCOPE_NAME","tags":"","loc":"proc/fpm_scope_name.html"},{"title":"FPM_UNIT_NAME – Fortran-lang/fpm","text":"public function FPM_UNIT_NAME(flag) result(name) Return the character name of a unit flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: flag Return Value character(len=:), allocatable Source Code function FPM_UNIT_NAME ( flag ) result ( name ) integer , intent ( in ) :: flag character ( len = :), allocatable :: name select case ( flag ) case ( FPM_UNIT_UNKNOWN ); name = \"FPM_UNIT_UNKNOWN\" case ( FPM_UNIT_PROGRAM ); name = \"FPM_UNIT_PROGRAM\" case ( FPM_UNIT_MODULE ); name = \"FPM_UNIT_MODULE\" case ( FPM_UNIT_SUBMODULE ); name = \"FPM_UNIT_SUBMODULE\" case ( FPM_UNIT_SUBPROGRAM ); name = \"FPM_UNIT_SUBPROGRAM\" case ( FPM_UNIT_CSOURCE ); name = \"FPM_UNIT_CSOURCE\" case ( FPM_UNIT_CPPSOURCE ); name = \"FPM_UNIT_CPPSOURCE\" case ( FPM_UNIT_CHEADER ); name = \"FPM_UNIT_CHEADER\" case default ; name = \"INVALID\" end select end function FPM_UNIT_NAME","tags":"","loc":"proc/fpm_unit_name.html"},{"title":"show_model – Fortran-lang/fpm","text":"public subroutine show_model(model) Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(in) :: model Source Code subroutine show_model ( model ) ! Prints a human readable representation of the Model type ( fpm_model_t ), intent ( in ) :: model print * , info_model ( model ) end subroutine show_model","tags":"","loc":"proc/show_model.html"},{"title":"change_directory – Fortran-lang/fpm","text":"public subroutine change_directory(path, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path type( error_t ), intent(out), allocatable :: error Source Code subroutine change_directory ( path , error ) character ( len =* ), intent ( in ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: cpath (:) integer :: stat allocate ( cpath ( len ( path ) + 1 )) call f_c_character ( path , cpath , len ( path ) + 1 ) stat = chdir_ ( cpath ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to change directory to '\" // path // \"'\" ) end if end subroutine change_directory","tags":"","loc":"proc/change_directory.html"},{"title":"convert_to_absolute_path – Fortran-lang/fpm","text":"public subroutine convert_to_absolute_path(path, error) Converts a path to an absolute, canonical path. Arguments Type Intent Optional Attributes Name character(len=:), intent(inout), allocatable :: path type( error_t ), intent(out), allocatable :: error","tags":"","loc":"proc/convert_to_absolute_path.html"},{"title":"get_absolute_path – Fortran-lang/fpm","text":"public subroutine get_absolute_path(path, absolute_path, error) Determine the canonical, absolute path for the given path.\nExpands home folder (~) on both Unix and Windows. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path character(len=:), intent(out), allocatable :: absolute_path type( error_t ), intent(out), allocatable :: error","tags":"","loc":"proc/get_absolute_path.html"},{"title":"get_absolute_path_by_cd – Fortran-lang/fpm","text":"public subroutine get_absolute_path_by_cd(path, absolute_path, error) Alternative to get_absolute_path that uses chdir / _chdir to determine the absolute path. get_absolute_path is preferred but get_absolute_path_by_cd can be used in bootstrap mode. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path character(len=:), intent(out), allocatable :: absolute_path type( error_t ), intent(out), allocatable :: error","tags":"","loc":"proc/get_absolute_path_by_cd.html"},{"title":"get_current_directory – Fortran-lang/fpm","text":"public subroutine get_current_directory(path, error) Arguments Type Intent Optional Attributes Name character(len=:), intent(out), allocatable :: path type( error_t ), intent(out), allocatable :: error Source Code subroutine get_current_directory ( path , error ) character ( len = :), allocatable , intent ( out ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: cpath (:) type ( c_ptr ) :: tmp allocate ( cpath ( buffersize )) tmp = getcwd_ ( cpath , buffersize ) if ( c_associated ( tmp )) then call c_f_character ( cpath , path ) else call fatal_error ( error , \"Failed to retrieve current directory\" ) end if end subroutine get_current_directory","tags":"","loc":"proc/get_current_directory.html"},{"title":"is_meta_package – Fortran-lang/fpm","text":"public function is_meta_package(key) Check local schema for allowed entries Supported metapackages Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: key Instance of the TOML data structure Return Value logical Source Code logical function is_meta_package ( key ) !> Instance of the TOML data structure character ( * ), intent ( in ) :: key select case ( key ) !> Supported metapackages case ( \"openmp\" , \"stdlib\" , \"mpi\" , \"minpack\" , \"hdf5\" ) is_meta_package = . true . case default is_meta_package = . false . end select end function is_meta_package","tags":"","loc":"proc/is_meta_package.html"},{"title":"new_meta_config – Fortran-lang/fpm","text":"public subroutine new_meta_config(self, table, meta_allowed, error) Construct a new build configuration from a TOML data structure The toml table is not checked here because it already passed\nthe “new_dependencies” check Arguments Type Intent Optional Attributes Name type( metapackage_config_t ), intent(out) :: self Instance of the build configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure logical, intent(in) :: meta_allowed (:) List of keys allowed to be metapackages type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_meta_config ( self , table , meta_allowed , error ) !> Instance of the build configuration type ( metapackage_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys allowed to be metapackages logical , intent ( in ) :: meta_allowed (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat !> The toml table is not checked here because it already passed !> the \"new_dependencies\" check call new_meta_request ( self % openmp , \"openmp\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % stdlib , \"stdlib\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % minpack , \"minpack\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % mpi , \"mpi\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % hdf5 , \"hdf5\" , table , meta_allowed , error ) if ( allocated ( error )) return end subroutine new_meta_config","tags":"","loc":"proc/new_meta_config.html"},{"title":"new_meta_request – Fortran-lang/fpm","text":"public subroutine new_meta_request(self, key, table, meta_allowed, error) Construct a new metapackage request from the dependencies table Set name\nThe toml table is not checked here because it already passed\nthe “new_dependencies” check Set list of entries that are allowed to be metapackages Arguments Type Intent Optional Attributes Name type( metapackage_request_t ), intent(out) :: self character(len=*), intent(in) :: key The package name type(toml_table), intent(inout) :: table Instance of the TOML data structure logical, intent(in), optional :: meta_allowed (:) List of keys allowed to be metapackages type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_meta_request ( self , key , table , meta_allowed , error ) type ( metapackage_request_t ), intent ( out ) :: self !> The package name character ( len =* ), intent ( in ) :: key !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys allowed to be metapackages logical , intent ( in ), optional :: meta_allowed (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , i character ( len = :), allocatable :: value logical , allocatable :: allow_meta (:) type ( toml_key ), allocatable :: keys (:) call request_destroy ( self ) !> Set name self % name = key if (. not . is_meta_package ( key )) then call fatal_error ( error , \"Error reading fpm.toml: <\" // key // \"> is not a valid metapackage name\" ) return end if !> The toml table is not checked here because it already passed !> the \"new_dependencies\" check call table % get_keys ( keys ) !> Set list of entries that are allowed to be metapackages if ( present ( meta_allowed )) then if ( size ( meta_allowed ) /= size ( keys )) then call fatal_error ( error , \"Internal error: list of metapackage-enable entries does not match table size\" ) return end if allow_meta = meta_allowed else allocate ( allow_meta ( size ( keys )), source = . true .) endif do i = 1 , size ( keys ) ! Skip standard dependencies if (. not . allow_meta ( i )) cycle if ( keys ( i )% key == key ) then call get_value ( table , key , value ) if (. not . allocated ( value )) then call syntax_error ( error , \"Could not retrieve version string for metapackage key <\" // key // \">. Check syntax\" ) return else call request_parse ( self , value , error ) return endif end if end do ! Key is not present, metapackage not requested return end subroutine new_meta_request","tags":"","loc":"proc/new_meta_request.html"},{"title":"cmd_publish – Fortran-lang/fpm","text":"public subroutine cmd_publish(settings) The publish command first builds the root package to obtain all the relevant information such as the\npackage version. It then creates a tarball of the package and uploads it to the registry.\nChecks before uploading the package. Arguments Type Intent Optional Attributes Name type( fpm_publish_settings ), intent(inout) :: settings","tags":"","loc":"proc/cmd_publish.html"},{"title":"new_example – Fortran-lang/fpm","text":"public subroutine new_example(self, table, error) Construct a new example configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( example_config_t ), intent(out) :: self Instance of the example configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_example ( self , table , error ) !> Instance of the example configuration type ( example_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve example name\" ) return end if if ( bad_name_error ( error , 'example' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"example\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_example","tags":"","loc":"proc/new_example.html"},{"title":"parse_c_source – Fortran-lang/fpm","text":"public function parse_c_source(c_filename, error) result(c_source) Parsing of c, cpp source files The following statements are recognised and parsed: #include preprocessor statement Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: c_filename type( error_t ), intent(out), allocatable :: error Return Value type( srcfile_t ) Source Code function parse_c_source ( c_filename , error ) result ( c_source ) character ( * ), intent ( in ) :: c_filename type ( srcfile_t ) :: c_source type ( error_t ), allocatable , intent ( out ) :: error integer :: fh , n_include , i , pass , stat type ( string_t ), allocatable :: file_lines (:) c_source % file_name = c_filename if ( str_ends_with ( lower ( c_filename ), \".c\" )) then c_source % unit_type = FPM_UNIT_CSOURCE else if ( str_ends_with ( lower ( c_filename ), \".h\" )) then c_source % unit_type = FPM_UNIT_CHEADER else if ( str_ends_with ( lower ( c_filename ), \".cpp\" )) then c_source % unit_type = FPM_UNIT_CPPSOURCE end if allocate ( c_source % modules_used ( 0 )) allocate ( c_source % modules_provided ( 0 )) allocate ( c_source % parent_modules ( 0 )) file_lines = read_lines ( c_filename ) ! Ignore empty files, returned as FPM_UNIT_UNKNOWN if ( len_trim ( file_lines ) < 1 ) then c_source % unit_type = FPM_UNIT_UNKNOWN return end if c_source % digest = fnv_1a ( file_lines ) do pass = 1 , 2 n_include = 0 file_loop : do i = 1 , size ( file_lines ) ! Process 'INCLUDE' statements if ( index ( adjustl ( lower ( file_lines ( i )% s )), '#include' ) == 1 . and . & index ( file_lines ( i )% s , '\"' ) > 0 ) then n_include = n_include + 1 if ( pass == 2 ) then c_source % include_dependencies ( n_include )% s = & & split_n ( file_lines ( i )% s , n = 2 , delims = '\"' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , c_filename , & 'unable to get c include file' , i , & file_lines ( i )% s , index ( file_lines ( i )% s , '\"' )) return end if end if end if end do file_loop if ( pass == 1 ) then allocate ( c_source % include_dependencies ( n_include )) end if end do end function parse_c_source","tags":"","loc":"proc/parse_c_source.html"},{"title":"parse_f_source – Fortran-lang/fpm","text":"public function parse_f_source(f_filename, error) result(f_source) Parsing of free-form fortran source files The following statements are recognised and parsed: Module / submodule / program declaration Module use statement include statement @note Note\n Intrinsic modules used by sources are not listed in\n the modules_used field of source objects. @note Note\n Submodules are treated as normal modules which use their\n corresponding parent modules. Parsing limitations Statements must not continued onto another line\n except for an only: list in the use statement. This is supported: use my_module , only : & my_var , my_function , my_subroutine This is NOT supported: use & my_module Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_filename type( error_t ), intent(out), allocatable :: error Return Value type( srcfile_t ) Source Code function parse_f_source ( f_filename , error ) result ( f_source ) character ( * ), intent ( in ) :: f_filename type ( srcfile_t ) :: f_source type ( error_t ), allocatable , intent ( out ) :: error logical :: inside_module , inside_interface , using , intrinsic_module integer :: stat integer :: fh , n_use , n_include , n_mod , n_parent , i , j , ic , pass type ( string_t ), allocatable :: file_lines (:), file_lines_lower (:) character (:), allocatable :: temp_string , mod_name , string_parts (:) if (. not . exists ( f_filename )) then call file_not_found_error ( error , f_filename ) return end if f_source % file_name = f_filename file_lines = read_lines_expanded ( f_filename ) ! for efficiency in parsing make a lowercase left-adjusted copy of the file ! Need a copy because INCLUDE (and #include) file arguments are case-sensitive file_lines_lower = file_lines do i = 1 , size ( file_lines_lower ) file_lines_lower ( i )% s = adjustl ( lower ( file_lines_lower ( i )% s )) enddo ! fnv_1a can only be applied to non-zero-length arrays if ( len_trim ( file_lines_lower ) > 0 ) f_source % digest = fnv_1a ( file_lines ) do pass = 1 , 2 n_use = 0 n_include = 0 n_mod = 0 n_parent = 0 inside_module = . false . inside_interface = . false . file_loop : do i = 1 , size ( file_lines_lower ) ! Skip comment lines and preprocessor directives if ( index ( file_lines_lower ( i )% s , '!' ) == 1 . or . & index ( file_lines_lower ( i )% s , '#' ) == 1 . or . & len_trim ( file_lines_lower ( i )% s ) < 1 ) then cycle end if ! Detect exported C-API via bind(C) if (. not . inside_interface . and . & parse_subsequence ( file_lines_lower ( i )% s , 'bind' , '(' , 'c' )) then do j = i , 1 , - 1 if ( index ( file_lines_lower ( j )% s , 'function' ) > 0 . or . & index ( file_lines_lower ( j )% s , 'subroutine' ) > 0 ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM exit end if if ( j > 1 ) then ic = index ( file_lines_lower ( j - 1 )% s , '!' ) if ( ic < 1 ) then ic = len ( file_lines_lower ( j - 1 )% s ) end if temp_string = trim ( file_lines_lower ( j - 1 )% s ( 1 : ic )) if ( index ( temp_string , '&' ) /= len ( temp_string )) then exit end if end if end do end if ! Skip lines that are continued: not statements if ( i > 1 ) then ic = index ( file_lines_lower ( i - 1 )% s , '!' ) if ( ic < 1 ) then ic = len ( file_lines_lower ( i - 1 )% s ) end if temp_string = trim ( file_lines_lower ( i - 1 )% s ( 1 : ic )) if ( len ( temp_string ) > 0 . and . index ( temp_string , '&' ) == len ( temp_string )) then cycle end if end if ! Detect beginning of interface block if ( index ( file_lines_lower ( i )% s , 'interface' ) == 1 & . or . parse_sequence ( file_lines_lower ( i )% s , 'abstract' , 'interface' )) then inside_interface = . true . cycle end if ! Detect end of interface block if ( parse_sequence ( file_lines_lower ( i )% s , 'end' , 'interface' )) then inside_interface = . false . cycle end if ! Process 'USE' statements call parse_use_statement ( f_filename , i , file_lines_lower ( i )% s , using , intrinsic_module , mod_name , error ) if ( allocated ( error )) return if ( using ) then ! Not a valid module name? if (. not . is_fortran_name ( mod_name )) cycle ! Valid intrinsic module: not a dependency if ( intrinsic_module ) cycle n_use = n_use + 1 if ( pass == 2 ) f_source % modules_used ( n_use )% s = mod_name cycle endif ! Process 'INCLUDE' statements ic = index ( file_lines_lower ( i )% s , 'include' ) if ( ic == 1 ) then ic = index ( lower ( file_lines ( i )% s ), 'include' ) if ( index ( adjustl ( file_lines ( i )% s ( ic + 7 :)), '\"' ) == 1 . or . & index ( adjustl ( file_lines ( i )% s ( ic + 7 :)), \"'\" ) == 1 ) then n_include = n_include + 1 if ( pass == 2 ) then f_source % include_dependencies ( n_include )% s = & & split_n ( file_lines ( i )% s , n = 2 , delims = \"'\" // '\"' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find include file name' , i , & file_lines ( i )% s ) return end if end if cycle end if end if ! Extract name of module if is module if ( index ( file_lines_lower ( i )% s , 'module ' ) == 1 ) then ! Remove any trailing comments ic = index ( file_lines_lower ( i )% s , '!' ) - 1 if ( ic < 1 ) then ic = len ( file_lines_lower ( i )% s ) end if temp_string = trim ( file_lines_lower ( i )% s ( 1 : ic )) ! R1405 module-stmt := \"MODULE\" module-name ! module-stmt has two space-delimited parts only ! (no line continuations) call split ( temp_string , string_parts , ' ' ) if ( size ( string_parts ) /= 2 ) then cycle end if mod_name = trim ( adjustl ( string_parts ( 2 ))) if ( scan ( mod_name , '=(&' ) > 0 ) then ! Ignore these cases: ! module & ! module =* ! module (i) cycle end if if (. not . is_fortran_name ( mod_name )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for module' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , mod_name )) return end if n_mod = n_mod + 1 if ( pass == 2 ) then f_source % modules_provided ( n_mod ) = string_t ( mod_name ) end if if ( f_source % unit_type == FPM_UNIT_UNKNOWN ) then f_source % unit_type = FPM_UNIT_MODULE end if if (. not . inside_module ) then inside_module = . true . else ! Must have missed an end module statement (can't assume a pure module) if ( f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if end if cycle end if ! Extract name of submodule if is submodule if ( index ( file_lines_lower ( i )% s , 'submodule' ) == 1 ) then mod_name = split_n ( file_lines_lower ( i )% s , n = 3 , delims = '()' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to get submodule name' , i , & file_lines_lower ( i )% s ) return end if if (. not . is_fortran_name ( mod_name )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for submodule' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , mod_name )) return end if n_mod = n_mod + 1 temp_string = split_n ( file_lines_lower ( i )% s , n = 2 , delims = '()' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to get submodule ancestry' , i , & file_lines_lower ( i )% s ) return end if if ( f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBMODULE end if n_use = n_use + 1 inside_module = . true . n_parent = n_parent + 1 if ( pass == 2 ) then if ( index ( temp_string , ':' ) > 0 ) then temp_string = temp_string ( index ( temp_string , ':' ) + 1 :) end if if (. not . is_fortran_name ( temp_string )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for submodule parent' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , temp_string )) return end if f_source % modules_used ( n_use )% s = temp_string f_source % parent_modules ( n_parent )% s = temp_string f_source % modules_provided ( n_mod )% s = mod_name end if cycle end if ! Detect if contains a program ! - no modules allowed after program def ! - program header may be missing (only \"end program\" statement present) if ( index ( file_lines_lower ( i )% s , 'program ' ) == 1 . or . & parse_sequence ( file_lines_lower ( i )% s , 'end' , 'program' )) then temp_string = split_n ( file_lines_lower ( i )% s , n = 2 , delims = ' ' , stat = stat ) if ( stat == 0 ) then if ( scan ( temp_string , '=(' ) > 0 ) then ! Ignore: ! program =* ! program (i) =* cycle end if end if f_source % unit_type = FPM_UNIT_PROGRAM cycle end if ! Parse end module statement ! (to check for code outside of modules) if ( parse_sequence ( file_lines_lower ( i )% s , 'end' , 'module' ) . or . & parse_sequence ( file_lines_lower ( i )% s , 'end' , 'submodule' )) then inside_module = . false . cycle end if ! Any statements not yet parsed are assumed to be other code statements if (. not . inside_module . and . f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if end do file_loop ! If unable to parse end of module statement, then can't assume pure module ! (there could be non-module subprograms present) if ( inside_module . and . f_source % unit_type == FPM_UNIT_MODULE ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if if ( pass == 1 ) then allocate ( f_source % modules_used ( n_use )) allocate ( f_source % include_dependencies ( n_include )) allocate ( f_source % modules_provided ( n_mod )) allocate ( f_source % parent_modules ( n_parent )) end if end do end function parse_f_source","tags":"","loc":"proc/parse_f_source.html"},{"title":"parse_use_statement – Fortran-lang/fpm","text":"public subroutine parse_use_statement(f_filename, i, line, use_stmt, is_intrinsic, module_name, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_filename Current file name and line number (for error messaging) integer, intent(in) :: i character(len=*), intent(in) :: line The line being parsed. MUST BE preprocessed with trim(adjustl() logical, intent(out) :: use_stmt Does this line contain a use statement? logical, intent(out) :: is_intrinsic Is the module in this statement intrinsic? character(len=:), intent(out), allocatable :: module_name used module name type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine parse_use_statement ( f_filename , i , line , use_stmt , is_intrinsic , module_name , error ) !> Current file name and line number (for error messaging) character ( * ), intent ( in ) :: f_filename integer , intent ( in ) :: i !> The line being parsed. MUST BE preprocessed with trim(adjustl() character ( * ), intent ( in ) :: line !> Does this line contain a `use` statement? logical , intent ( out ) :: use_stmt !> Is the module in this statement intrinsic? logical , intent ( out ) :: is_intrinsic !> used module name character (:), allocatable , intent ( out ) :: module_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( 15 ), parameter :: INTRINSIC_NAMES ( * ) = & [ 'iso_c_binding ' , & 'iso_fortran_env' , & 'ieee_arithmetic' , & 'ieee_exceptions' , & 'ieee_features ' , & 'omp_lib ' ] character ( len = :), allocatable :: temp_string integer :: colons , intr , nonintr , j , stat logical :: has_intrinsic_name use_stmt = . false . is_intrinsic = . false . if ( len_trim ( line ) <= 0 ) return ! Quick check that the line is preprocessed if ( line ( 1 : 1 ) == ' ' ) then call fatal_error ( error , 'internal_error: source file line is not trim(adjustl()) on input to parse_use_statement' ) return end if ! 'use' should be the first string in the adjustl line use_stmt = index ( line , 'use ' ) == 1 . or . index ( line , 'use::' ) == 1 . or . index ( line , 'use,' ) == 1 if (. not . use_stmt ) return colons = index ( line , '::' ) nonintr = 0 intr = 0 have_colons : if ( colons > 3 ) then ! there may be an intrinsic/non-intrinsic spec nonintr = index ( line ( 1 : colons - 1 ), 'non_intrinsic' ) if ( nonintr == 0 ) intr = index ( line ( 1 : colons - 1 ), 'intrinsic' ) temp_string = split_n ( line , delims = ':' , n = 2 , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line , colons ) return end if module_name = split_n ( temp_string , delims = ' ,' , n = 1 , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line ) return end if else module_name = split_n ( line , n = 2 , delims = ' ,' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line ) return end if end if have_colons ! If declared intrinsic, check that it is true has_intrinsic_name = any ([( index ( module_name , trim ( INTRINSIC_NAMES ( j ))) > 0 , & j = 1 , size ( INTRINSIC_NAMES ))]) if ( intr > 0 . and . . not . has_intrinsic_name ) then ! An intrinsic module was not found. Its name could be in the next line, ! in which case, we just skip this check. The compiler will do the job if the name is invalid. ! Module name was not read: it's in the next line if ( index ( module_name , '&' ) <= 0 ) then call file_parse_error ( error , f_filename , & 'module ' // module_name // ' is declared intrinsic but it is not ' , i , & line ) return endif endif ! Should we treat this as an intrinsic module is_intrinsic = nonintr == 0 . and . & ! not declared non-intrinsic ( intr > 0 . or . has_intrinsic_name ) end subroutine parse_use_statement","tags":"","loc":"proc/parse_use_statement.html"},{"title":"new_executable – Fortran-lang/fpm","text":"public subroutine new_executable(self, table, error) Construct a new executable configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( executable_config_t ), intent(out) :: self Instance of the executable configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_executable ( self , table , error ) !> Instance of the executable configuration type ( executable_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve executable name\" ) return end if if ( bad_name_error ( error , 'executable' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"app\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_executable","tags":"","loc":"proc/new_executable.html"},{"title":"cmd_new – Fortran-lang/fpm","text":"public subroutine cmd_new(settings) TOP DIRECTORY NAME PROCESSING\nsee if requested new directory already exists and process appropriately\ntemporarily change to new directory as a test. NB: System dependent Arguments Type Intent Optional Attributes Name type( fpm_new_settings ), intent(in) :: settings Source Code subroutine cmd_new ( settings ) type ( fpm_new_settings ), intent ( in ) :: settings integer , parameter :: tfc = selected_char_kind ( 'DEFAULT' ) character ( len = :, kind = tfc ), allocatable :: bname ! baeename of NAME character ( len = :, kind = tfc ), allocatable :: tomlfile (:) character ( len = :, kind = tfc ), allocatable :: littlefile (:) !> TOP DIRECTORY NAME PROCESSING !> see if requested new directory already exists and process appropriately if ( exists ( settings % name ) . and . . not . settings % backfill ) then write ( stderr , '(*(g0,1x))' )& & '' , settings % name , 'already exists.' write ( stderr , '(*(g0,1x))' )& & ' perhaps you wanted to add --backfill ?' return elseif ( is_dir ( settings % name ) . and . settings % backfill ) then write ( * , '(*(g0))' ) 'backfilling ' , settings % name elseif ( exists ( settings % name ) ) then write ( stderr , '(*(g0,1x))' )& & '' , settings % name , 'already exists and is not a directory.' return else ! make new directory call mkdir ( settings % name ) endif !> temporarily change to new directory as a test. NB: System dependent call run ( 'cd ' // settings % name ) ! NOTE: need some system routines to handle filenames like \".\" ! like realpath() or getcwd(). bname = basename ( settings % name ) littlefile = [ character ( len = 80 ) :: '# ' // bname , 'My cool new project!' ] ! create NAME/README.md call warnwrite ( join_path ( settings % name , 'README.md' ), littlefile ) ! start building NAME/fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: & & ' # This is your fpm(Fortran Package Manager) manifest file ' ,& & ' # (\"fpm.toml\"). It is heavily annotated to help guide you though ' ,& & ' # customizing a package build, although the defaults are sufficient ' ,& & ' # for many basic packages. ' ,& & ' # ' ,& & ' # The manifest file is not only used to provide metadata identifying ' ,& & ' # your project (so it can be used by others as a dependency). It can ' ,& & ' # specify where your library and program sources live, what the name ' ,& & ' # of the executable(s) will be, what files to build, dependencies on ' ,& & ' # other fpm packages, and what external libraries are required. ' ,& & ' # ' ,& & ' # The manifest format must conform to the TOML configuration file ' ,& & ' # standard. ' ,& & ' # ' ,& & ' # TOML files support flexible use of white-space and commenting of the ' ,& & ' # configuration data, but for clarity in this sample active directives ' ,& & ' # begin in column one. Inactive example directives are commented ' ,& & ' # out with a pound character (\"#\") but begin in column one as well. ' ,& & ' # Commentary begins with a pound character in column three. ' ,& & ' # ' ,& & ' # This file draws heavily upon the following references: ' ,& & ' # ' ,& & ' # The fpm home page at ' ,& & ' # https://github.com/fortran-lang/fpm ' ,& & ' # A complete list of keys and their attributes at ' ,& & ' # https://github.com/fortran-lang/fpm/blob/main/manifest-reference.md ' ,& & ' # examples of fpm project packaging at ' ,& & ' # https://github.com/fortran-lang/fpm/blob/main/PACKAGING.md ' ,& & ' # The Fortran TOML file interface and it''s references at ' ,& & ' # https://github.com/toml-f/toml-f ' ,& & ' # ' ,& & ' #----------------------- ' ,& & ' # project Identification ' ,& & ' #----------------------- ' ,& & ' # We begin with project metadata at the manifest root. This data is designed ' ,& & ' # to aid others when searching for the project in a repository and to ' ,& & ' # identify how and when to contact the package supporters. ' ,& & ' ' ,& & 'name = \"' // bname // '\"' ,& & ' # The project name (required) is how the project will be referred to. ' ,& & ' # The name is used by other packages using it as a dependency. It also ' ,& & ' # is used as the default name of any library built and the optional ' ,& & ' # default executable built from app/main.f90. It must conform to the rules ' ,& & ' # for a Fortran variable name. ' ,& & ' ' ,& & 'version = \"0.1.0\" ' ,& & ' # The project version number is a string. A recommended scheme for ' ,& & ' # specifying versions is the Semantic Versioning scheme. ' ,& & ' ' ,& & 'license = \"license\" ' ,& & ' # Licensing information specified using SPDX identifiers is preferred ' ,& & ' # (eg. \"Apache-2.0 OR MIT\" or \"LGPL-3.0-or-later\"). ' ,& & ' ' ,& & 'maintainer = \"jane.doe@example.com\" ' ,& & ' # Information on the project maintainer and means to reach out to them. ' ,& & ' ' ,& & 'author = \"Jane Doe\" ' ,& & ' # Information on the project author. ' ,& & ' ' ,& & 'copyright = \"Copyright 2020 Jane Doe\" ' ,& & ' # A statement clarifying the Copyright status of the project. ' ,& & ' ' ,& & '#description = \"A short project summary in plain text\" ' ,& & ' # The description provides a short summary on the project. It should be ' ,& & ' # plain text and not use any markup formatting. ' ,& & ' ' ,& & '#categories = [\"fortran\", \"graphics\"] ' ,& & ' # Categories associated with the project. Listing only one is preferred. ' ,& & ' ' ,& & '#keywords = [\"hdf5\", \"mpi\"] ' ,& & ' # The keywords field is an array of strings describing the project. ' ,& & ' ' ,& & '#homepage = \"https://stdlib.fortran-lang.org\" ' ,& & ' # URL to the webpage of the project. ' ,& & ' ' ,& & ' # ----------------------------------------- ' ,& & ' # We are done with identifying the project. ' ,& & ' # ----------------------------------------- ' ,& & ' # ' ,& & ' # Now lets start describing how the project should be built. ' ,& & ' # ' ,& & ' # Note tables would go here but we will not be talking about them (much)!!' ,& & ' # ' ,& & ' # Tables are a way to explicitly specify large numbers of programs in ' ,& & ' # a compact format instead of individual per-program entries in the ' ,& & ' # [[executable]], [[test]], and [[example]] sections to follow but ' ,& & ' # will not be discussed further except for the following notes: ' ,& & ' # ' ,& & ' # + Tables must appear (here) before any sections are declared. Once a ' ,& & ' # section is specified in a TOML file everything afterwards must be ' ,& & ' # values for that section or the beginning of a new section. A simple ' ,& & ' # example looks like: ' ,& & ' ' ,& & '#executable = [ ' ,& & '# { name = \"a-prog\" }, ' ,& & '# { name = \"app-tool\", source-dir = \"tool\" }, ' ,& & '# { name = \"fpm-man\", source-dir = \"tool\", main=\"fman.f90\" } ' ,& & '#] ' ,& & ' ' ,& & ' # This would be in lieue of the [[executable]] section found later in this ' ,& & ' # configuration file. ' ,& & ' # + See the reference documents (at the beginning of this document) ' ,& & ' # for more information on tables if you have long lists of programs ' ,& & ' # to build and are not simply depending on auto-detection. ' ,& & ' # ' ,& & ' # Now lets begin the TOML sections (lines beginning with \"[\") ... ' ,& & ' # ' ,& & ' ' ,& & '[install] # Options for the \"install\" subcommand ' ,& & ' ' ,& & ' # When you run the \"install\" subcommand only executables are installed by ' ,& & ' # default on the local system. Library projects that will be used outside of ' ,& & ' # \"fpm\" can set the \"library\" boolean to also allow installing the module ' ,& & ' # files and library archive. Without this being set to \"true\" an \"install\" ' ,& & ' # subcommand ignores parameters that specify library installation. ' ,& & ' ' ,& & 'library = false ' ,& & ' ' ,& & '[build] # General Build Options ' ,& & ' ' ,& & ' ### Automatic target discovery ' ,& & ' # ' ,& & ' # Normally fpm recursively searches the app/, example/, and test/ directories ' ,& & ' # for program sources and builds them. To disable this automatic discovery of ' ,& & ' # program targets set the following to \"false\": ' ,& & ' ' ,& & '#auto-executables = true ' ,& & '#auto-examples = true ' ,& & '#auto-tests = true ' ,& & ' ' ,& & ' ### Package-level External Library Links ' ,& & ' # ' ,& & ' # To declare link-time dependencies on external libraries a list of ' ,& & ' # native libraries can be specified with the \"link\" entry. You may ' ,& & ' # have one library name or a list of strings in case several ' ,& & ' # libraries should be linked. This list of library dependencies is ' ,& & ' # exported to dependent packages. You may have to alter your library ' ,& & ' # search-path to ensure the libraries can be accessed. Typically, ' ,& & ' # this is done with the LD_LIBRARY_PATH environment variable on ULS ' ,& & ' # (Unix-Like Systems). You only specify the core name of the library ' ,& & ' # (as is typical with most programming environments, where you ' ,& & ' # would specify \"-lz\" on your load command to link against the zlib ' ,& & ' # compression library even though the library file would typically be ' ,& & ' # a file called \"libz.a\" \"or libz.so\"). So to link against that library ' ,& & ' # you would specify: ' ,& & ' ' ,& & '#link = \"z\" ' ,& & ' ' ,& & ' # Note that in some cases the order of the libraries matters: ' ,& & ' ' ,& & '#link = [\"blas\", \"lapack\"] ' ,& & '' ] endif if ( settings % with_bare ) then elseif ( settings % with_lib ) then call mkdir ( join_path ( settings % name , 'src' ) ) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & '[library] ' ,& & ' ' ,& & ' # You can change the name of the directory to search for your library ' ,& & ' # source from the default of \"src/\". Library targets are exported ' ,& & ' # and usable by other projects. ' ,& & ' ' ,& & 'source-dir=\"src\" ' ,& & ' ' ,& & ' # this can be a list: ' ,& & ' ' ,& & '#source-dir=[\"src\", \"src2\"] ' ,& & ' ' ,& & ' # More complex libraries may organize their modules in subdirectories. ' ,& & ' # For modules in a top-level directory fpm requires (but does not ' ,& & ' # enforce) that: ' ,& & ' # ' ,& & ' # + The module has the same name as the source file. This is important. ' ,& & ' # + There should be only one module per file. ' ,& & ' # ' ,& & ' # These two requirements simplify the build process for fpm. As Fortran ' ,& & ' # compilers emit module files (.mod) with the same name as the module ' ,& & ' # itself (but not the source file, .f90), naming the module the same ' ,& & ' # as the source file allows fpm to: ' ,& & ' # ' ,& & ' # + Uniquely and exactly map a source file (.f90) to its object (.o) ' ,& & ' # and module (.mod) files. ' ,& & ' # + Avoid conflicts with modules of the same name that could appear ' ,& & ' # in dependency packages. ' ,& & ' # ' ,& & ' ### Multi-level library source ' ,& & ' # You can place your module source files in any number of levels of ' ,& & ' # subdirectories inside your source directory, but there are certain naming ' ,& & ' # conventions to be followed -- module names must contain the path components ' ,& & ' # of the directory that its source file is in. ' ,& & ' # ' ,& & ' # This rule applies generally to any number of nested directories and ' ,& & ' # modules. For example, src/a/b/c/d.f90 must define a module called a_b_c_d. ' ,& & ' # Again, this is not enforced but may be required in future releases. ' ,& & '' ] endif ! create placeholder module src/bname.f90 littlefile = [ character ( len = 80 ) :: & & 'module ' // to_fortran_name ( bname ), & & ' implicit none' , & & ' private' , & & '' , & & ' public :: say_hello' , & & 'contains' , & & ' subroutine say_hello' , & & ' print *, \"Hello, ' // bname // '!\"' , & & ' end subroutine say_hello' , & & 'end module ' // to_fortran_name ( bname )] ! create NAME/src/NAME.f90 call warnwrite ( join_path ( settings % name , 'src' , bname // '.f90' ),& & littlefile ) endif if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile ,& & '[dependencies] ' ,& & ' ' ,& & ' # Inevitably, you will want to be able to include other packages in ' ,& & ' # a project. Fpm makes this incredibly simple, by taking care of ' ,& & ' # fetching and compiling your dependencies for you. You just tell it ' ,& & ' # what your dependencies names are, and where to find them. ' ,& & ' # ' ,& & ' # If you are going to distribute your package only place dependencies ' ,& & ' # here someone using your package as a remote dependency needs built. ' ,& & ' # You can define dependencies just for developer executables in the ' ,& & ' # next section, or even for specific executables as we will see below ' ,& & ' # (Then fpm will still fetch and compile it when building your ' ,& & ' # developer executables, but users of your library will not have to). ' ,& & ' # ' ,& & ' ## GLOBAL DEPENDENCIES (exported with your project) ' ,& & ' # ' ,& & ' # Typically, dependencies are defined by specifying the project''s ' ,& & ' # git repository. ' ,& & ' # ' ,& & ' # You can be specific about which version of a dependency you would ' ,& & ' # like. By default the latest default branch is used. You can ' ,& & ' # optionally specify a branch, a tag or a commit value. ' ,& & ' # ' ,& & ' # So here are several alternates for specifying a remote dependency (you ' ,& & ' # can have at most one of \"branch\", \"rev\" or \"tag\" present): ' ,& & ' ' ,& & '#stdlib = { git = \"https://github.com/LKedward/stdlib-fpm.git\" } ' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\",branch = \"master\" },' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\", tag = \"v0.1.0\" }, ' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\", rev = \"5a9b7a8\" }. ' ,& & ' ' ,& & ' # There may be multiple packages listed: ' ,& & ' ' ,& & '#M_strings = { git = \"https://github.com/urbanjost/M_strings.git\" } ' ,& & '#M_time = { git = \"https://github.com/urbanjost/M_time.git\" } ' ,& & ' ' ,& & ' # ' ,& & ' # You can even specify the local path to another project if it is in ' ,& & ' # a sub-folder (If for example you have got another fpm package **in ' ,& & ' # the same repository**) like this: ' ,& & ' ' ,& & '#M_strings = { path = \"M_strings\" } ' ,& & ' ' ,& & ' # This tells fpm that we depend on a crate called M_strings which is found ' ,& & ' # in the M_strings folder (relative to the fpm.toml it’s written in). ' ,& & ' # ' ,& & ' # For a more verbose layout use normal tables rather than inline tables ' ,& & ' # to specify dependencies: ' ,& & ' ' ,& & '#[dependencies.toml-f] ' ,& & '#git = \"https://github.com/toml-f/toml-f\" ' ,& & '#rev = \"2f5eaba864ff630ba0c3791126a3f811b6e437f3\" ' ,& & ' ' ,& & ' # Now you can use any modules from these libraries anywhere in your ' ,& & ' # code -- whether is in your library source or a program source. ' ,& & ' ' ,& & '[dev-dependencies] ' ,& & ' ' ,& & ' ## Dependencies Only for Development ' ,& & ' # ' ,& & ' # You can specify dependencies your library or application does not ' ,& & ' # depend on in a similar way. The difference is that these will not ' ,& & ' # be exported as part of your project to those using it as a remote ' ,& & ' # dependency. ' ,& & ' # ' ,& & ' # Currently, like a global dependency it will still be available for ' ,& & ' # all codes. It is up to the developer to ensure that nothing except ' ,& & ' # developer test programs rely upon it. ' ,& & ' ' ,& & '#M_msg = { git = \"https://github.com/urbanjost/M_msg.git\" } ' ,& & '#M_verify = { git = \"https://github.com/urbanjost/M_verify.git\" } ' ,& & '' ] endif if ( settings % with_bare ) then elseif ( settings % with_executable ) then ! create next section of fpm.toml call mkdir ( join_path ( settings % name , 'app' )) ! create NAME/app or stop if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & ' #----------------------------------- ' ,& & ' ## Application-specific declarations ' ,& & ' #----------------------------------- ' ,& & ' # Now lets begin entries for the TOML tables (lines beginning with \"[[\") ' ,& & ' # that describe the program sources -- applications, tests, and examples. ' ,& & ' # ' ,& & ' # First we will configuration individual applications run with \"fpm run\". ' ,& & ' # ' ,& & ' # + the \"name\" entry for the executable to be built must always ' ,& & ' # be specified. The name must satisfy the rules for a Fortran ' ,& & ' # variable name. This will be the name of the binary installed by ' ,& & ' # the \"install\" subcommand and used on the \"run\" subcommand. ' ,& & ' # + The source directory for each executable can be adjusted by the ' ,& & ' # \"source-dir\" entry. ' ,& & ' # + The basename of the source file containing the program body can ' ,& & ' # be specified with the \"main\" entry. ' ,& & ' # + Executables can also specify their own external package and ' ,& & ' # library link dependencies. ' ,& & ' # ' ,& & ' # Currently, like a global dependency any external package dependency ' ,& & ' # will be available for all codes. It is up to the developer to ensure ' ,& & ' # that nothing except the application programs specified rely upon it. ' ,& & ' # ' ,& & ' # Note if your application needs to use a module internally, but you do not ' ,& & ' # intend to build it as a library to be used in other projects, you can ' ,& & ' # include the module in your program source file or directory as well. ' ,& & ' ' ,& & '[[executable]] ' ,& & 'name=\"' // bname // '\"' ,& & 'source-dir=\"app\" ' ,& & 'main=\"main.f90\" ' ,& & ' ' ,& & ' # You may repeat this pattern to define additional applications. For instance,' ,& & ' # the following sample illustrates all accepted options, where \"link\" and ' ,& & ' # \"executable.dependencies\" keys are the same as the global external library ' ,& & ' # links and package dependencies described previously except they apply ' ,& & ' # only to this executable: ' ,& & ' ' ,& & '#[[ executable ]] ' ,& & '#name = \"app-name\" ' ,& & '#source-dir = \"prog\" ' ,& & '#main = \"program.f90\" ' ,& & '#link = \"z\" ' ,& & '#[executable.dependencies] ' ,& & '#M_CLI = { git = \"https://github.com/urbanjost/M_CLI.git\" } ' ,& & '#helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } ' ,& & '#M_path = { git = \"https://github.com/urbanjost/M_path.git\" } ' ,& & '' ] endif if ( exists ( bname // '/src/' )) then littlefile = [ character ( len = 80 ) :: & & 'program main' , & & ' use ' // to_fortran_name ( bname ) // ', only: say_hello' , & & ' implicit none' , & & '' , & & ' call say_hello()' , & & 'end program main' ] else littlefile = [ character ( len = 80 ) :: & & 'program main' , & & ' implicit none' , & & '' , & & ' print *, \"hello from project ' // bname // '\"' , & & 'end program main' ] endif call warnwrite ( join_path ( settings % name , 'app/main.f90' ), littlefile ) endif if ( settings % with_bare ) then elseif ( settings % with_test ) then ! create NAME/test or stop call mkdir ( join_path ( settings % name , 'test' )) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile ,& & '[[test]] ' ,& & ' ' ,& & ' # The same declarations can be made for test programs, which are ' ,& & ' # executed with the \"fpm test\" command and are not build when your ' ,& & ' # package is used as a dependency by other packages. These are ' ,& & ' # typically unit tests of the package only used during package ' ,& & ' # development. ' ,& & ' ' ,& & 'name=\"runTests\" ' ,& & 'source-dir=\"test\" ' ,& & 'main=\"check.f90\" ' ,& & ' ' ,& & ' # you may repeat this pattern to add additional explicit test program ' ,& & ' # parameters. The following example contains a sample of all accepted ' ,& & ' # options. ' ,& & ' ' ,& & '#[[ test ]] ' ,& & '#name = \"tester\" ' ,& & '#source-dir=\"test\" ' ,& & '#main=\"tester.f90\" ' ,& & '#link = [\"blas\", \"lapack\"] ' ,& & '#[test.dependencies] ' ,& & '#M_CLI2 = { git = \"https://github.com/urbanjost/M_CLI2.git\" } ' ,& & '#M_io = { git = \"https://github.com/urbanjost/M_io.git\" } ' ,& & '#M_system= { git = \"https://github.com/urbanjost/M_system.git\" } ' ,& & '' ] endif littlefile = [ character ( len = 80 ) :: & & 'program check' , & & 'implicit none' , & & '' , & & 'print *, \"Put some tests in here!\"' , & & 'end program check' ] ! create NAME/test/check.f90 call warnwrite ( join_path ( settings % name , 'test/check.f90' ), littlefile ) endif if ( settings % with_bare ) then elseif ( settings % with_example ) then ! create NAME/example or stop call mkdir ( join_path ( settings % name , 'example' )) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & '[[example]] ' ,& & ' ' ,& & ' # Example applications for a project are defined here. ' ,& & ' # These are run via \"fpm run --example NAME\" and like the ' ,& & ' # test applications, are not built when this package is used as a ' ,& & ' # dependency by other packages. ' ,& & ' ' ,& & 'name=\"demo\" ' ,& & 'source-dir=\"example\" ' ,& & 'main=\"demo.f90\" ' ,& & ' ' ,& & ' # ' ,& & ' # you may add additional programs to the example table. The following ' ,& & ' # example contains a sample of all accepted options ' ,& & ' ' ,& & '#[[ example ]] ' ,& & '#name = \"example-tool\" ' ,& & '#source-dir=\"example\" ' ,& & '#main=\"tool.f90\" ' ,& & '#link = \"z\" ' ,& & '#[example.dependencies] ' ,& & '#M_kracken95 = { git = \"https://github.com/urbanjost/M_kracken95.git\" } ' ,& & '#datetime = {git = \"https://github.com/wavebitscientific/datetime-fortran.git\" }' ,& & '' ] endif littlefile = [ character ( len = 80 ) :: & & 'program demo' , & & 'implicit none' , & & '' , & & 'print *, \"Put some examples in here!\"' , & & 'end program demo' ] ! create NAME/example/demo.f90 call warnwrite ( join_path ( settings % name , 'example/demo.f90' ), littlefile ) endif ! now that built it write NAME/fpm.toml if ( allocated ( tomlfile ) ) then call validate_toml_data ( tomlfile ) call warnwrite ( join_path ( settings % name , 'fpm.toml' ), tomlfile ) else call create_verified_basic_manifest ( join_path ( settings % name , 'fpm.toml' )) endif ! assumes git(1) is installed and in path if ( which ( 'git' ) /= '' ) then call run ( 'git init ' // settings % name ) endif contains function git_metadata ( what ) result ( returned ) !> get metadata values such as email address and git name from git(1) or return appropriate default use fpm_filesystem , only : get_temp_filename , getline character ( len =* ), intent ( in ) :: what ! keyword designating what git metatdata to query character ( len = :), allocatable :: returned ! value to return for requested keyword character ( len = :), allocatable :: command character ( len = :), allocatable :: temp_filename character ( len = :), allocatable :: iomsg character ( len = :), allocatable :: temp_value integer :: stat , unit temp_filename = get_temp_filename () ! for known keywords set default value for RETURNED and associated git(1) command for query select case ( what ) case ( 'uname' ) returned = \"Jane Doe\" command = \"git config --get user.name > \" // temp_filename case ( 'email' ) returned = \"jane.doe@example.com\" command = \"git config --get user.email > \" // temp_filename case default write ( stderr , '(*(g0,1x))' )& & ' *git_metadata* unknown metadata name ' , trim ( what ) returned = '' return end select ! Execute command if git(1) is in command path if ( which ( 'git' ) /= '' ) then call run ( command , exitstat = stat ) if ( stat /= 0 ) then ! If command failed just return default return else ! Command did not return an error so try to read expected output file open ( file = temp_filename , newunit = unit , iostat = stat ) if ( stat == 0 ) then ! Read file into a scratch variable until status of doing so is checked call getline ( unit , temp_value , stat , iomsg ) if ( stat == 0 . and . temp_value /= '' ) then ! Return output from successful command returned = temp_value endif endif ! Always do the CLOSE because a failed open has unpredictable results. ! Add IOSTAT so a failed close does not cause program to stop close ( unit , status = \"delete\" , iostat = stat ) endif endif end function git_metadata subroutine create_verified_basic_manifest ( filename ) !> create a basic but verified default manifest file use fpm_toml , only : toml_table , toml_serialize , set_value use fpm_manifest_package , only : package_config_t , new_package use fpm_error , only : error_t implicit none character ( len =* ), intent ( in ) :: filename type ( toml_table ) :: table type ( package_config_t ) :: package type ( error_t ), allocatable :: error integer :: lun character ( len = 8 ) :: date character (:), allocatable :: output if ( exists ( filename )) then write ( stderr , '(*(g0,1x))' ) ' ' , filename ,& & 'already exists. Not overwriting' return endif !> get date to put into metadata in manifest file \"fpm.toml\" call date_and_time ( DATE = date ) table = toml_table () call fileopen ( filename , lun ) ! fileopen stops on error call set_value ( table , \"name\" , BNAME ) call set_value ( table , \"version\" , \"0.1.0\" ) call set_value ( table , \"license\" , \"license\" ) call set_value ( table , \"author\" , git_metadata ( 'uname' )) call set_value ( table , \"maintainer\" , git_metadata ( 'email' )) call set_value ( table , \"copyright\" , 'Copyright ' // date ( 1 : 4 ) // ', ' // git_metadata ( 'uname' )) ! continue building of manifest ! ... call new_package ( package , table , error = error ) if ( allocated ( error )) call fpm_stop ( 3 , '' ) output = toml_serialize ( table ) if ( settings % verbose ) then print '(a)' , output endif write ( lun , '(a)' ) output call fileclose ( lun ) ! fileopen stops on error end subroutine create_verified_basic_manifest subroutine validate_toml_data ( input ) !> verify a string array is a valid fpm.toml file ! use tomlf , only : toml_load use fpm_toml , only : toml_table , toml_serialize implicit none character ( kind = tfc , len = :), intent ( in ), allocatable :: input (:) character ( len = 1 ), parameter :: nl = new_line ( 'a' ) type ( toml_table ), allocatable :: table character ( kind = tfc , len = :), allocatable :: joined_string ! you have to add a newline character by using the intrinsic ! function `new_line(\"a\")` to get the lines processed correctly. joined_string = join ( input , right = nl ) if ( allocated ( table )) deallocate ( table ) call toml_load ( table , joined_string ) if ( allocated ( table )) then if ( settings % verbose ) then ! If the TOML file is successfully parsed the table will be allocated and ! can be written by `toml_serialize` to the standard output print '(a)' , toml_serialize ( table ) endif call table % destroy endif end subroutine validate_toml_data end subroutine cmd_new","tags":"","loc":"proc/cmd_new.html"},{"title":"get_global_settings – Fortran-lang/fpm","text":"public subroutine get_global_settings(global_settings, error) Obtain global settings from the global config file. Arguments Type Intent Optional Attributes Name type( fpm_global_settings ), intent(inout) :: global_settings Global settings to be obtained. type( error_t ), intent(out), allocatable :: error Error reading config file.","tags":"","loc":"proc/get_global_settings.html"},{"title":"get_registry_settings – Fortran-lang/fpm","text":"public subroutine get_registry_settings(table, global_settings, error) Read registry settings from the global config file. Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout), target :: table The [registry] subtable from the global config file. type( fpm_global_settings ), intent(inout) :: global_settings The global settings which can be filled with the registry settings. type( error_t ), intent(out), allocatable :: error Error handling.","tags":"","loc":"proc/get_registry_settings.html"},{"title":"new_library – Fortran-lang/fpm","text":"public subroutine new_library(self, table, error) Construct a new library configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( library_config_t ), intent(out) :: self Instance of the library configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_library ( self , table , error ) !> Instance of the library configuration type ( library_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"source-dir\" , self % source_dir , \"src\" ) call get_value ( table , \"build-script\" , self % build_script ) call get_list ( table , \"include-dir\" , self % include_dir , error ) if ( allocated ( error )) return ! Set default value of include-dir if not found in manifest if (. not . allocated ( self % include_dir )) then self % include_dir = [ string_t ( \"include\" )] end if end subroutine new_library","tags":"","loc":"proc/new_library.html"},{"title":"ar_is_same – Fortran-lang/fpm","text":"public function ar_is_same(this, that) Check that two archiver_t objects are equal\nAll checks passed! Type Bound archiver_t Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Source Code logical function ar_is_same ( this , that ) class ( archiver_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that ar_is_same = . false . select type ( other => that ) type is ( archiver_t ) if (. not .( this % ar == other % ar )) return if (. not .( this % use_response_file . eqv . other % use_response_file )) return if (. not .( this % echo . eqv . other % echo )) return if (. not .( this % verbose . eqv . other % verbose )) return class default ! Not the same type return end select !> All checks passed! ar_is_same = . true . end function ar_is_same","tags":"","loc":"proc/ar_is_same.html"},{"title":"check_compiler – Fortran-lang/fpm","text":"public function check_compiler(compiler, expected) result(match) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler character(len=*), intent(in) :: expected Return Value logical Source Code function check_compiler ( compiler , expected ) result ( match ) character ( len =* ), intent ( in ) :: compiler character ( len =* ), intent ( in ) :: expected logical :: match match = compiler == expected if (. not . match ) then match = index ( basename ( compiler ), expected ) > 0 end if end function check_compiler","tags":"","loc":"proc/check_compiler.html"},{"title":"check_fortran_source_runs – Fortran-lang/fpm","text":"public function check_fortran_source_runs(self, input) result(success) Run a single-source Fortran program using the current compiler\nCompile a Fortran object\nCreate temporary source file\nWrite contents\nCompile and link program\nRun and retrieve exit code Successful exit on 0 exit code Delete files Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Program Source Return Value logical Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: exe character(len=:), public, allocatable :: logf character(len=:), public, allocatable :: object character(len=:), public, allocatable :: source integer, public :: stat integer, public :: unit Source Code logical function check_fortran_source_runs ( self , input ) result ( success ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Program Source character ( len =* ), intent ( in ) :: input integer :: stat , unit character (:), allocatable :: source , object , logf , exe success = . false . !> Create temporary source file exe = get_temp_filename () source = exe // '.f90' object = exe // '.o' logf = exe // '.log' open ( newunit = unit , file = source , action = 'readwrite' , iostat = stat ) if ( stat /= 0 ) return !> Write contents write ( unit , * ) input close ( unit ) !> Compile and link program call self % compile_fortran ( source , object , self % get_default_flags ( release = . false .), logf , stat ) if ( stat == 0 ) & call self % link ( exe , self % get_default_flags ( release = . false .) // \" \" // object , logf , stat ) !> Run and retrieve exit code if ( stat == 0 ) & call run ( exe , echo = . false ., exitstat = stat , verbose = . false ., redirect = logf ) !> Successful exit on 0 exit code success = stat == 0 !> Delete files open ( newunit = unit , file = source , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = object , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = logf , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = exe , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) end function check_fortran_source_runs","tags":"","loc":"proc/check_fortran_source_runs.html"},{"title":"compiler_is_same – Fortran-lang/fpm","text":"public function compiler_is_same(this, that) Check that two compiler_t objects are equal\nAll checks passed! Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Source Code logical function compiler_is_same ( this , that ) class ( compiler_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that compiler_is_same = . false . select type ( other => that ) type is ( compiler_t ) if (. not .( this % id == other % id )) return if (. not .( this % fc == other % fc )) return if (. not .( this % cc == other % cc )) return if (. not .( this % cxx == other % cxx )) return if (. not .( this % echo . eqv . other % echo )) return if (. not .( this % verbose . eqv . other % verbose )) return class default ! Not the same type return end select !> All checks passed! compiler_is_same = . true . end function compiler_is_same","tags":"","loc":"proc/compiler_is_same.html"},{"title":"compiler_name – Fortran-lang/fpm","text":"public pure function compiler_name(self) result(name) Return a compiler name string Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string Source Code pure function compiler_name ( self ) result ( name ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: name select case ( self % id ) case ( id_gcc ); name = \"gfortran\" case ( id_f95 ); name = \"f95\" case ( id_caf ); name = \"caf\" case ( id_intel_classic_nix ); name = \"ifort\" case ( id_intel_classic_mac ); name = \"ifort\" case ( id_intel_classic_windows ); name = \"ifort\" case ( id_intel_llvm_nix ); name = \"ifx\" case ( id_intel_llvm_windows ); name = \"ifx\" case ( id_intel_llvm_unknown ); name = \"ifx\" case ( id_pgi ); name = \"pgfortran\" case ( id_nvhpc ); name = \"nvfortran\" case ( id_nag ); name = \"nagfor\" case ( id_flang ); name = \"flang\" case ( id_flang_new ); name = \"flang-new\" case ( id_f18 ); name = \"f18\" case ( id_ibmxl ); name = \"xlf90\" case ( id_cray ); name = \"crayftn\" case ( id_lahey ); name = \"lfc\" case ( id_lfortran ); name = \"lFortran\" case default ; name = \"invalid/unknown\" end select end function compiler_name","tags":"","loc":"proc/compiler_name.html"},{"title":"debug_archiver – Fortran-lang/fpm","text":"public pure function debug_archiver(self) result(repr) String representation of an archiver object Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(in) :: self Instance of the archiver object Return Value character(len=:), allocatable Representation as string Source Code pure function debug_archiver ( self ) result ( repr ) !> Instance of the archiver object type ( archiver_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: repr repr = 'ar=\"' // self % ar // '\"' end function debug_archiver","tags":"","loc":"proc/debug_archiver.html"},{"title":"debug_compiler – Fortran-lang/fpm","text":"public pure function debug_compiler(self) result(repr) String representation of a compiler object Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string Source Code pure function debug_compiler ( self ) result ( repr ) !> Instance of the compiler object type ( compiler_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: repr repr = 'fc=\"' // self % fc // '\", cc=\"' // self % cc // '\"' end function debug_compiler","tags":"","loc":"proc/debug_compiler.html"},{"title":"enumerate_libraries – Fortran-lang/fpm","text":"public function enumerate_libraries(self, prefix, libs) result(r) Enumerate libraries, based on compiler and platform Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: prefix type( string_t ), intent(in) :: libs (:) Return Value character(len=:), allocatable Source Code function enumerate_libraries ( self , prefix , libs ) result ( r ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: prefix type ( string_t ), intent ( in ) :: libs (:) character ( len = :), allocatable :: r if ( self % id == id_intel_classic_windows . or . & self % id == id_intel_llvm_windows ) then r = prefix // \" \" // string_cat ( libs , \".lib \" ) // \".lib\" else r = prefix // \" -l\" // string_cat ( libs , \" -l\" ) end if end function enumerate_libraries","tags":"","loc":"proc/enumerate_libraries.html"},{"title":"get_compiler_id – Fortran-lang/fpm","text":"public function get_compiler_id(compiler) result(id) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler Return Value integer(kind=compiler_enum) Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: command character(len=:), public, allocatable :: full_command character(len=:), public, allocatable :: full_command_parts (:) integer, public :: io character(len=:), public, allocatable :: output integer, public :: stat Source Code function get_compiler_id ( compiler ) result ( id ) character ( len =* ), intent ( in ) :: compiler integer ( kind = compiler_enum ) :: id character ( len = :), allocatable :: full_command , full_command_parts (:), command , output integer :: stat , io ! Check whether we are dealing with an MPI compiler wrapper first if ( check_compiler ( compiler , \"mpifort\" ) & & . or . check_compiler ( compiler , \"mpif90\" ) & & . or . check_compiler ( compiler , \"mpif77\" )) then output = get_temp_filename () call run ( compiler // \" -show > \" // output // \" 2>&1\" , & & echo = . false ., exitstat = stat ) if ( stat == 0 ) then open ( file = output , newunit = io , iostat = stat ) if ( stat == 0 ) call getline ( io , full_command , stat ) close ( io , iostat = stat ) ! If we get a command from the wrapper, we will try to identify it call split ( full_command , full_command_parts , delimiters = ' ' ) if ( size ( full_command_parts ) > 0 ) then command = trim ( full_command_parts ( 1 )) endif if ( allocated ( command )) then id = get_id ( command ) if ( id /= id_unknown ) return end if end if end if id = get_id ( compiler ) end function get_compiler_id","tags":"","loc":"proc/get_compiler_id.html"},{"title":"get_default_flags – Fortran-lang/fpm","text":"public function get_default_flags(self, release) result(flags) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self logical, intent(in) :: release Return Value character(len=:), allocatable Source Code function get_default_flags ( self , release ) result ( flags ) class ( compiler_t ), intent ( in ) :: self logical , intent ( in ) :: release character ( len = :), allocatable :: flags if ( release ) then call get_release_compile_flags ( self % id , flags ) else call get_debug_compile_flags ( self % id , flags ) end if end function get_default_flags","tags":"","loc":"proc/get_default_flags.html"},{"title":"get_feature_flag – Fortran-lang/fpm","text":"public function get_feature_flag(self, feature) result(flags) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: feature Return Value character(len=:), allocatable Source Code function get_feature_flag ( self , feature ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: feature character ( len = :), allocatable :: flags flags = \"\" select case ( feature ) case ( \"no-implicit-typing\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_no_implicit_typing case ( id_nag ) flags = flag_nag_no_implicit_typing case ( id_cray ) flags = flag_cray_no_implicit_typing end select case ( \"implicit-typing\" ) select case ( self % id ) case ( id_cray ) flags = flag_cray_implicit_typing case ( id_lfortran ) flags = flag_lfortran_implicit_typing end select case ( \"no-implicit-external\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_no_implicit_external end select case ( \"implicit-external\" ) select case ( self % id ) case ( id_lfortran ) flags = flag_lfortran_implicit_external end select case ( \"free-form\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_free_form case ( id_pgi , id_nvhpc , id_flang ) flags = flag_pgi_free_form case ( id_nag ) flags = flag_nag_free_form case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , & & id_intel_llvm_unknown ) flags = flag_intel_free_form case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = flag_intel_free_form_win case ( id_cray ) flags = flag_cray_free_form end select case ( \"fixed-form\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_fixed_form case ( id_pgi , id_nvhpc , id_flang ) flags = flag_pgi_fixed_form case ( id_nag ) flags = flag_nag_fixed_form case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , & & id_intel_llvm_unknown ) flags = flag_intel_fixed_form case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = flag_intel_fixed_form_win case ( id_cray ) flags = flag_cray_fixed_form case ( id_lfortran ) flags = flag_lfortran_fixed_form end select case ( \"default-form\" ) continue case default error stop \"Unknown feature '\" // feature // \"'\" end select end function get_feature_flag","tags":"","loc":"proc/get_feature_flag.html"},{"title":"get_id – Fortran-lang/fpm","text":"public function get_id(compiler) result(id) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler Return Value integer(kind=compiler_enum) Source Code function get_id ( compiler ) result ( id ) character ( len =* ), intent ( in ) :: compiler integer ( kind = compiler_enum ) :: id if ( check_compiler ( compiler , \"gfortran\" )) then id = id_gcc return end if if ( check_compiler ( compiler , \"f95\" )) then id = id_f95 return end if if ( check_compiler ( compiler , \"caf\" )) then id = id_caf return end if if ( check_compiler ( compiler , \"ifort\" )) then select case ( get_os_type ()) case default id = id_intel_classic_nix case ( OS_MACOS ) id = id_intel_classic_mac case ( OS_WINDOWS , OS_CYGWIN ) id = id_intel_classic_windows end select return end if if ( check_compiler ( compiler , \"ifx\" )) then select case ( get_os_type ()) case default id = id_intel_llvm_nix case ( OS_WINDOWS , OS_CYGWIN ) id = id_intel_llvm_windows end select return end if if ( check_compiler ( compiler , \"nvfortran\" )) then id = id_nvhpc return end if if ( check_compiler ( compiler , \"pgfortran\" ) & & . or . check_compiler ( compiler , \"pgf90\" ) & & . or . check_compiler ( compiler , \"pgf95\" )) then id = id_pgi return end if if ( check_compiler ( compiler , \"nagfor\" )) then id = id_nag return end if if ( check_compiler ( compiler , \"flang-new\" )) then id = id_flang_new return end if if ( check_compiler ( compiler , \"f18\" )) then id = id_f18 return end if if ( check_compiler ( compiler , \"flang\" )) then id = id_flang return end if if ( check_compiler ( compiler , \"xlf90\" )) then id = id_ibmxl return end if if ( check_compiler ( compiler , \"crayftn\" )) then id = id_cray return end if if ( check_compiler ( compiler , \"lfc\" )) then id = id_lahey return end if if ( check_compiler ( compiler , \"lfortran\" )) then id = id_lfortran return end if id = id_unknown end function get_id","tags":"","loc":"proc/get_id.html"},{"title":"get_include_flag – Fortran-lang/fpm","text":"public function get_include_flag(self, path) result(flags) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function get_include_flag ( self , path ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: flags select case ( self % id ) case default flags = \"-I \" // path case ( id_caf , id_gcc , id_f95 , id_cray , id_nvhpc , id_pgi , & & id_flang , id_flang_new , id_f18 , & & id_intel_classic_nix , id_intel_classic_mac , & & id_intel_llvm_nix , id_lahey , id_nag , id_ibmxl , & & id_lfortran ) flags = \"-I \" // path case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = \"/I\" // path end select end function get_include_flag","tags":"","loc":"proc/get_include_flag.html"},{"title":"get_macros – Fortran-lang/fpm","text":"public function get_macros(id, macros_list, version) result(macros) This function will parse and read the macros list and\nreturn them as defined flags.\nSet macro defintion symbol on the basis of compiler used\nCheck if macros are not allocated.\nSplit the macro name and value. Check if the value of macro starts with ‘{’ character. Check if the value of macro ends with ‘}’ character. Check if the string contains “version” as substring. These conditions are placed in order to ensure proper spacing between the macros. Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id type( string_t ), intent(in), allocatable :: macros_list (:) character(len=:), intent(in), allocatable :: version Return Value character(len=:), allocatable Variables Type Visibility Attributes Name Initial integer, public :: i character(len=:), public, allocatable :: macro_definition_symbol character(len=:), public, allocatable :: valued_macros (:) Source Code function get_macros ( id , macros_list , version ) result ( macros ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( in ) :: version type ( string_t ), allocatable , intent ( in ) :: macros_list (:) character ( len = :), allocatable :: macros character ( len = :), allocatable :: macro_definition_symbol character (:), allocatable :: valued_macros (:) integer :: i if (. not . allocated ( macros_list )) then macros = \"\" return end if !> Set macro defintion symbol on the basis of compiler used select case ( id ) case default macro_definition_symbol = \" -D\" case ( id_intel_classic_windows , id_intel_llvm_windows ) macro_definition_symbol = \" /D\" end select !> Check if macros are not allocated. if (. not . allocated ( macros )) then macros = \"\" end if do i = 1 , size ( macros_list ) !> Split the macro name and value. call split ( macros_list ( i )% s , valued_macros , delimiters = \"=\" ) if ( size ( valued_macros ) > 1 ) then !> Check if the value of macro starts with '{' character. if ( str_begins_with_str ( trim ( valued_macros ( size ( valued_macros ))), \"{\" )) then !> Check if the value of macro ends with '}' character. if ( str_ends_with ( trim ( valued_macros ( size ( valued_macros ))), \"}\" )) then !> Check if the string contains \"version\" as substring. if ( index ( valued_macros ( size ( valued_macros )), \"version\" ) /= 0 ) then !> These conditions are placed in order to ensure proper spacing between the macros. macros = macros // macro_definition_symbol // trim ( valued_macros ( 1 )) // '=' // version cycle end if end if end if end if macros = macros // macro_definition_symbol // macros_list ( i )% s end do end function get_macros","tags":"","loc":"proc/get_macros.html"},{"title":"get_module_flag – Fortran-lang/fpm","text":"public function get_module_flag(self, path) result(flags) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function get_module_flag ( self , path ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: flags select case ( self % id ) case default flags = \"-module \" // path case ( id_caf , id_gcc , id_f95 , id_cray , id_lfortran ) flags = \"-J \" // path case ( id_nvhpc , id_pgi , id_flang ) flags = \"-module \" // path case ( id_flang_new , id_f18 ) flags = \"-module-dir \" // path case ( id_intel_classic_nix , id_intel_classic_mac , & & id_intel_llvm_nix ) flags = \"-module \" // path case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = \"/module:\" // path case ( id_lahey ) flags = \"-M \" // path case ( id_nag ) flags = \"-mdir \" // path case ( id_ibmxl ) flags = \"-qmoddir \" // path end select end function get_module_flag","tags":"","loc":"proc/get_module_flag.html"},{"title":"is_gnu – Fortran-lang/fpm","text":"public pure function is_gnu(self) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical Source Code pure logical function is_gnu ( self ) class ( compiler_t ), intent ( in ) :: self is_gnu = any ( self % id == [ id_f95 , id_gcc , id_caf ]) end function is_gnu","tags":"","loc":"proc/is_gnu.html"},{"title":"is_intel – Fortran-lang/fpm","text":"public pure function is_intel(self) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical Source Code pure logical function is_intel ( self ) class ( compiler_t ), intent ( in ) :: self is_intel = any ( self % id == [ id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows , & id_intel_llvm_nix , id_intel_llvm_windows , id_intel_llvm_unknown ]) end function is_intel","tags":"","loc":"proc/is_intel.html"},{"title":"is_unknown – Fortran-lang/fpm","text":"public pure function is_unknown(self) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical Source Code pure function is_unknown ( self ) class ( compiler_t ), intent ( in ) :: self logical :: is_unknown is_unknown = self % id == id_unknown end function is_unknown","tags":"","loc":"proc/is_unknown.html"},{"title":"with_qp – Fortran-lang/fpm","text":"public function with_qp(self) Check if the current compiler supports 128-bit real precision Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical Source Code logical function with_qp ( self ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self with_qp = self % check_fortran_source_runs & ( 'if (selected_real_kind(33) == -1) stop 1; end' ) end function with_qp","tags":"","loc":"proc/with_qp.html"},{"title":"with_xdp – Fortran-lang/fpm","text":"public function with_xdp(self) Check if the current compiler supports 80-bit “extended” real precision Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical Source Code logical function with_xdp ( self ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self with_xdp = self % check_fortran_source_runs & ( 'if (any(selected_real_kind(18) == [-1, selected_real_kind(33)])) stop 1; end' ) end function with_xdp","tags":"","loc":"proc/with_xdp.html"},{"title":"compile_c – Fortran-lang/fpm","text":"public subroutine compile_c(self, input, output, args, log_file, stat) Compile a C object Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Source Code subroutine compile_c ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % cc // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_c","tags":"","loc":"proc/compile_c.html"},{"title":"compile_cpp – Fortran-lang/fpm","text":"public subroutine compile_cpp(self, input, output, args, log_file, stat) Compile a CPP object Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Source Code subroutine compile_cpp ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % cxx // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_cpp","tags":"","loc":"proc/compile_cpp.html"},{"title":"compile_fortran – Fortran-lang/fpm","text":"public subroutine compile_fortran(self, input, output, args, log_file, stat) Compile a Fortran object Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Source Code subroutine compile_fortran ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % fc // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_fortran","tags":"","loc":"proc/compile_fortran.html"},{"title":"compiler_dump – Fortran-lang/fpm","text":"public subroutine compiler_dump(self, table, error) Dump dependency to toml table Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Variables Type Visibility Attributes Name Initial integer, public :: ierr Source Code subroutine compiler_dump ( self , table , error ) !> Instance of the serializable object class ( compiler_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_value ( table , \"id\" , self % id , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"fc\" , self % fc , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"cc\" , self % cc , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"cxx\" , self % cxx , error , 'compiler_t' ) if ( allocated ( error )) return call set_value ( table , \"echo\" , self % echo , error , 'compiler_t' ) if ( allocated ( error )) return call set_value ( table , \"verbose\" , self % verbose , error , 'compiler_t' ) if ( allocated ( error )) return end subroutine compiler_dump","tags":"","loc":"proc/compiler_dump.html"},{"title":"compiler_load – Fortran-lang/fpm","text":"public subroutine compiler_load(self, table, error) Read dependency from toml table (no checks made at this stage) Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine compiler_load ( self , table , error ) !> Instance of the serializable object class ( compiler_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"id\" , self % id , error , 'compiler_t' ) if ( allocated ( error )) return call get_value ( table , \"fc\" , self % fc ) call get_value ( table , \"cc\" , self % cc ) call get_value ( table , \"cxx\" , self % cxx ) call get_value ( table , \"echo\" , self % echo , error , 'compiler_t' ) if ( allocated ( error )) return call get_value ( table , \"verbose\" , self % verbose , error , 'compiler_t' ) if ( allocated ( error )) return end subroutine compiler_load","tags":"","loc":"proc/compiler_load.html"},{"title":"dump_to_toml – Fortran-lang/fpm","text":"public subroutine dump_to_toml(self, table, error) Dump dependency to toml table Path to archiver Type Bound archiver_t Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( archiver_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Path to archiver call set_string ( table , \"ar\" , self % ar , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"use-response-file\" , self % use_response_file , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"echo\" , self % echo , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"verbose\" , self % verbose , error , 'archiver_t' ) if ( allocated ( error )) return end subroutine dump_to_toml","tags":"","loc":"proc/dump_to_toml~9.html"},{"title":"get_debug_compile_flags – Fortran-lang/fpm","text":"public subroutine get_debug_compile_flags(id, flags) Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(out), allocatable :: flags Source Code subroutine get_debug_compile_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( out ) :: flags select case ( id ) case default flags = \"\" case ( id_caf ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & flag_gnu_backtrace case ( id_gcc ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & flag_gnu_backtrace // & flag_gnu_coarray case ( id_f95 ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & ' -Wno-maybe-uninitialized -Wno-uninitialized' // & flag_gnu_backtrace case ( id_nvhpc ) flags = & flag_pgi_warn // & flag_pgi_backslash // & flag_pgi_check // & flag_pgi_traceback case ( id_ibmxl ) flags = & flag_ibmxl_backslash case ( id_intel_classic_nix ) flags = & flag_intel_warn // & flag_intel_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_classic_mac ) flags = & flag_intel_warn // & flag_intel_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_classic_windows ) flags = & flag_intel_warn_win // & flag_intel_check_win // & flag_intel_limit_win // & flag_intel_debug_win // & flag_intel_byterecl_win // & flag_intel_backtrace_win case ( id_intel_llvm_nix ) flags = & flag_intel_warn // & flag_intel_llvm_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_llvm_windows ) flags = & flag_intel_warn_win // & flag_intel_check_win // & flag_intel_limit_win // & flag_intel_debug_win // & flag_intel_byterecl_win case ( id_nag ) flags = & flag_nag_debug // & flag_nag_check // & flag_nag_backtrace // & flag_nag_coarray // & flag_nag_pic case ( id_lfortran ) flags = \"\" end select end subroutine get_debug_compile_flags","tags":"","loc":"proc/get_debug_compile_flags.html"},{"title":"get_default_c_compiler – Fortran-lang/fpm","text":"public subroutine get_default_c_compiler(f_compiler, c_compiler) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_compiler character(len=:), intent(out), allocatable :: c_compiler Variables Type Visibility Attributes Name Initial integer(kind=compiler_enum), public :: id Source Code subroutine get_default_c_compiler ( f_compiler , c_compiler ) character ( len =* ), intent ( in ) :: f_compiler character ( len = :), allocatable , intent ( out ) :: c_compiler integer ( compiler_enum ) :: id id = get_compiler_id ( f_compiler ) select case ( id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows ) c_compiler = 'icc' case ( id_intel_llvm_nix , id_intel_llvm_windows ) c_compiler = 'icx' case ( id_flang , id_flang_new , id_f18 ) c_compiler = 'clang' case ( id_ibmxl ) c_compiler = 'xlc' case ( id_lfortran ) c_compiler = 'cc' case ( id_gcc ) c_compiler = 'gcc' case default ! Fall-back to using Fortran compiler c_compiler = f_compiler end select end subroutine get_default_c_compiler","tags":"","loc":"proc/get_default_c_compiler.html"},{"title":"get_default_cxx_compiler – Fortran-lang/fpm","text":"public subroutine get_default_cxx_compiler(f_compiler, cxx_compiler) Get C++ Compiler. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_compiler character(len=:), intent(out), allocatable :: cxx_compiler Variables Type Visibility Attributes Name Initial integer(kind=compiler_enum), public :: id Source Code subroutine get_default_cxx_compiler ( f_compiler , cxx_compiler ) character ( len =* ), intent ( in ) :: f_compiler character ( len = :), allocatable , intent ( out ) :: cxx_compiler integer ( compiler_enum ) :: id id = get_compiler_id ( f_compiler ) select case ( id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows ) cxx_compiler = 'icpc' case ( id_intel_llvm_nix , id_intel_llvm_windows ) cxx_compiler = 'icpx' case ( id_flang , id_flang_new , id_f18 ) cxx_compiler = 'clang++' case ( id_ibmxl ) cxx_compiler = 'xlc++' case ( id_lfortran ) cxx_compiler = 'cc' case ( id_gcc ) cxx_compiler = 'g++' case default ! Fall-back to using Fortran compiler cxx_compiler = f_compiler end select end subroutine get_default_cxx_compiler","tags":"","loc":"proc/get_default_cxx_compiler.html"},{"title":"get_main_flags – Fortran-lang/fpm","text":"public subroutine get_main_flags(self, language, flags) Get special flags for the main linker Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: language character(len=:), intent(out), allocatable :: flags Source Code subroutine get_main_flags ( self , language , flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: language character ( len = :), allocatable , intent ( out ) :: flags flags = \"\" select case ( language ) case ( \"fortran\" ) flags = \"\" case ( \"c\" ) ! If the main program is on a C/C++ source, the Intel Fortran compiler requires option ! -nofor-main to avoid \"duplicate main\" errors. ! https://stackoverflow.com/questions/36221612/p3dfft-compilation-ifort-compiler-error-multiple-definiton-of-main select case ( self % id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix ) flags = '-nofor-main' case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = '/nofor-main' case ( id_pgi , id_nvhpc ) flags = '-Mnomain' end select case ( \"c++\" , \"cpp\" , \"cxx\" ) select case ( self % id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix ) flags = '-nofor-main' case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = '/nofor-main' case ( id_pgi , id_nvhpc ) flags = '-Mnomain' end select case default error stop \"Unknown language '\" // language // '\", try \"fortran\", \"c\", \"c++\"' end select end subroutine get_main_flags","tags":"","loc":"proc/get_main_flags.html"},{"title":"get_release_compile_flags – Fortran-lang/fpm","text":"public subroutine get_release_compile_flags(id, flags) Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(out), allocatable :: flags Source Code subroutine get_release_compile_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( out ) :: flags select case ( id ) case default flags = \"\" case ( id_caf ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit case ( id_gcc ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_coarray case ( id_f95 ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit case ( id_nvhpc ) flags = & flag_pgi_backslash case ( id_ibmxl ) flags = & flag_ibmxl_backslash case ( id_intel_classic_nix ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_classic_mac ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_classic_windows ) flags = & flag_intel_opt_win // & flag_intel_fp_win // & flag_intel_align_win // & flag_intel_limit_win // & flag_intel_pthread_win // & flag_intel_nogen_win // & flag_intel_byterecl_win case ( id_intel_llvm_nix ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_llvm_windows ) flags = & flag_intel_opt_win // & flag_intel_fp_win // & flag_intel_align_win // & flag_intel_limit_win // & flag_intel_pthread_win // & flag_intel_nogen_win // & flag_intel_byterecl_win case ( id_nag ) flags = & flag_nag_opt // & flag_nag_coarray // & flag_nag_pic case ( id_lfortran ) flags = & flag_lfortran_opt end select end subroutine get_release_compile_flags","tags":"","loc":"proc/get_release_compile_flags.html"},{"title":"link – Fortran-lang/fpm","text":"public subroutine link(self, output, args, log_file, stat) Link an executable Type Bound compiler_t Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Source Code subroutine link ( self , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % fc // \" \" // args // \" -o \" // output , echo = self % echo , & & verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine link","tags":"","loc":"proc/link.html"},{"title":"load_from_toml – Fortran-lang/fpm","text":"public subroutine load_from_toml(self, table, error) Read dependency from toml table (no checks made at this stage) Type Bound archiver_t Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( archiver_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"ar\" , self % ar ) call get_value ( table , \"use-response-file\" , self % use_response_file , error , 'archiver_t' ) if ( allocated ( error )) return call get_value ( table , \"echo\" , self % echo , error , 'archiver_t' ) if ( allocated ( error )) return call get_value ( table , \"verbose\" , self % verbose , error , 'archiver_t' ) if ( allocated ( error )) return end subroutine load_from_toml","tags":"","loc":"proc/load_from_toml~9.html"},{"title":"make_archive – Fortran-lang/fpm","text":"public subroutine make_archive(self, output, args, log_file, stat) Create an archive Todo For Windows OS, use the local delete_file_win32 in stead of delete_file .\nThis may be related to a bug in Mingw64-openmp and is expected to be resolved in the future,\nsee issue #707, #708 and #808. Type Bound archiver_t Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: self Instance of the archiver object character(len=*), intent(in) :: output Name of the archive to generate type( string_t ), intent(in) :: args (:) Object files to include into the archive character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag Subroutines subroutine delete_file_win32 (file) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file Source Code subroutine make_archive ( self , output , args , log_file , stat ) !> Instance of the archiver object class ( archiver_t ), intent ( in ) :: self !> Name of the archive to generate character ( len =* ), intent ( in ) :: output !> Object files to include into the archive type ( string_t ), intent ( in ) :: args (:) !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat if ( self % use_response_file ) then call write_response_file ( output // \".resp\" , args ) call run ( self % ar // output // \" @\" // output // \".resp\" , echo = self % echo , & & verbose = self % verbose , redirect = log_file , exitstat = stat ) call delete_file_win32 ( output // \".resp\" ) else call run ( self % ar // output // \" \" // string_cat ( args , \" \" ), & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end if contains subroutine delete_file_win32 ( file ) character ( len =* ), intent ( in ) :: file logical :: exist integer :: unit , iostat inquire ( file = file , exist = exist ) if ( exist ) then open ( file = file , newunit = unit ) close ( unit , status = 'delete' , iostat = iostat ) end if end subroutine delete_file_win32 end subroutine make_archive","tags":"","loc":"proc/make_archive.html"},{"title":"new_archiver – Fortran-lang/fpm","text":"public subroutine new_archiver(self, ar, echo, verbose) Create new archiver instance Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(out) :: self New instance of the archiver character(len=*), intent(in) :: ar User provided archiver command logical, intent(in) :: echo Echo compiler command logical, intent(in) :: verbose Verbose mode: dump compiler output Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: arflags = \" -rs \" integer, public :: estat character(len=*), public, parameter :: libflags = \" /OUT:\" integer, public :: os_type Source Code subroutine new_archiver ( self , ar , echo , verbose ) !> New instance of the archiver type ( archiver_t ), intent ( out ) :: self !> User provided archiver command character ( len =* ), intent ( in ) :: ar !> Echo compiler command logical , intent ( in ) :: echo !> Verbose mode: dump compiler output logical , intent ( in ) :: verbose integer :: estat , os_type character ( len =* ), parameter :: arflags = \" -rs \" , libflags = \" /OUT:\" if ( len_trim ( ar ) > 0 ) then ! Check first for ar-like commands if ( check_compiler ( ar , \"ar\" )) then self % ar = ar // arflags end if ! Check for lib-like commands if ( check_compiler ( ar , \"lib\" )) then self % ar = ar // libflags end if ! Fallback and assume ar-like behaviour self % ar = ar // arflags else os_type = get_os_type () if ( os_type /= OS_WINDOWS . and . os_type /= OS_UNKNOWN ) then self % ar = \"ar\" // arflags else ! Attempt \"ar\" call execute_command_line ( \"ar --version > \" // get_temp_filename () // \" 2>&1\" , & & exitstat = estat ) if ( estat == 0 ) then self % ar = \"ar\" // arflags else ! Then \"gcc-ar\" call execute_command_line ( \"gcc-ar --version > \" // get_temp_filename () // \" 2>&1\" , & & exitstat = estat ) if ( estat /= 0 ) then self % ar = \"lib\" // libflags else self % ar = \"gcc-ar\" // arflags end if endif end if end if self % use_response_file = os_type == OS_WINDOWS self % echo = echo self % verbose = verbose end subroutine new_archiver","tags":"","loc":"proc/new_archiver.html"},{"title":"new_compiler – Fortran-lang/fpm","text":"public subroutine new_compiler(self, fc, cc, cxx, echo, verbose) Create new compiler instance Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(out) :: self New instance of the compiler character(len=*), intent(in) :: fc Fortran compiler name or path character(len=*), intent(in) :: cc C compiler name or path character(len=*), intent(in) :: cxx C++ Compiler name or path logical, intent(in) :: echo Echo compiler command logical, intent(in) :: verbose Verbose mode: dump compiler output Source Code subroutine new_compiler ( self , fc , cc , cxx , echo , verbose ) !> New instance of the compiler type ( compiler_t ), intent ( out ) :: self !> Fortran compiler name or path character ( len =* ), intent ( in ) :: fc !> C compiler name or path character ( len =* ), intent ( in ) :: cc !> C++ Compiler name or path character ( len =* ), intent ( in ) :: cxx !> Echo compiler command logical , intent ( in ) :: echo !> Verbose mode: dump compiler output logical , intent ( in ) :: verbose self % id = get_compiler_id ( fc ) self % echo = echo self % verbose = verbose self % fc = fc if ( len_trim ( cc ) > 0 ) then self % cc = cc else call get_default_c_compiler ( self % fc , self % cc ) end if if ( len_trim ( cxx ) > 0 ) then self % cxx = cxx else call get_default_cxx_compiler ( self % fc , self % cxx ) end if end subroutine new_compiler","tags":"","loc":"proc/new_compiler.html"},{"title":"set_cpp_preprocessor_flags – Fortran-lang/fpm","text":"public pure subroutine set_cpp_preprocessor_flags(id, flags) Modify the flag_cpp_preprocessor on the basis of the compiler. Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(inout), allocatable :: flags Variables Type Visibility Attributes Name Initial character(len=:), public, allocatable :: flag_cpp_preprocessor Source Code pure subroutine set_cpp_preprocessor_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( inout ) :: flags character ( len = :), allocatable :: flag_cpp_preprocessor !> Modify the flag_cpp_preprocessor on the basis of the compiler. select case ( id ) case default flag_cpp_preprocessor = \"\" case ( id_caf , id_gcc , id_f95 , id_nvhpc ) flag_cpp_preprocessor = \"-cpp\" case ( id_intel_classic_windows , id_intel_llvm_windows ) flag_cpp_preprocessor = \"/fpp\" case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , id_nag ) flag_cpp_preprocessor = \"-fpp\" case ( id_lfortran ) flag_cpp_preprocessor = \"--cpp\" end select flags = flag_cpp_preprocessor // flags end subroutine set_cpp_preprocessor_flags","tags":"","loc":"proc/set_cpp_preprocessor_flags.html"},{"title":"write_response_file – Fortran-lang/fpm","text":"public subroutine write_response_file(name, argv) Response files allow to read command line options from files.\nWhitespace is used to separate the arguments, we will use newlines\nas separator to create readable response files which can be inspected\nin case of errors. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name type( string_t ), intent(in) :: argv (:) Variables Type Visibility Attributes Name Initial integer, public :: iarg integer, public :: io Source Code subroutine write_response_file ( name , argv ) character ( len =* ), intent ( in ) :: name type ( string_t ), intent ( in ) :: argv (:) integer :: iarg , io open ( file = name , newunit = io , status = 'replace' ) do iarg = 1 , size ( argv ) write ( io , '(a)' ) unix_path ( argv ( iarg )% s ) end do close ( io ) end subroutine write_response_file","tags":"","loc":"proc/write_response_file.html"},{"title":"debug – Fortran-lang/fpm","text":"public interface debug Create debug printout Module Procedures public pure function debug_compiler (self) result(repr) String representation of a compiler object Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string public pure function debug_archiver (self) result(repr) String representation of an archiver object Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(in) :: self Instance of the archiver object Return Value character(len=:), allocatable Representation as string","tags":"","loc":"interface/debug.html"},{"title":"bad_name_error – Fortran-lang/fpm","text":"public function bad_name_error(error, label, name) Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: label Error message label to add to message character(len=*), intent(in) :: name name value to check Return Value logical Source Code function bad_name_error ( error , label , name ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message label to add to message character ( len =* ), intent ( in ) :: label !> name value to check character ( len =* ), intent ( in ) :: name logical :: bad_name_error if (. not . is_fortran_name ( to_fortran_name ( name ))) then bad_name_error = . true . allocate ( error ) error % message = 'manifest file syntax error: ' // label // ' name must be composed only of & &alphanumerics, \"-\" and \"_\" and start with a letter ::' // name else bad_name_error = . false . endif end function bad_name_error","tags":"","loc":"proc/bad_name_error.html"},{"title":"fatal_error – Fortran-lang/fpm","text":"public subroutine fatal_error(error, message) Generic fatal runtime error Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: message Error message Source Code subroutine fatal_error ( error , message ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message character ( len =* ), intent ( in ) :: message allocate ( error ) error % message = message end subroutine fatal_error","tags":"","loc":"proc/fatal_error.html"},{"title":"file_not_found_error – Fortran-lang/fpm","text":"public subroutine file_not_found_error(error, file_name) Error created when a file is missing or not found Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: file_name Name of the missing file Source Code subroutine file_not_found_error ( error , file_name ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Name of the missing file character ( len =* ), intent ( in ) :: file_name allocate ( error ) error % message = \"'\" // file_name // \"' could not be found, check if the file exists\" end subroutine file_not_found_error","tags":"","loc":"proc/file_not_found_error.html"},{"title":"file_parse_error – Fortran-lang/fpm","text":"public subroutine file_parse_error(error, file_name, message, line_num, line_string, line_col) Error created when file parsing fails Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: file_name Name of file character(len=*), intent(in) :: message Parse error message integer, intent(in), optional :: line_num Line number of parse error character(len=*), intent(in), optional :: line_string Line context string integer, intent(in), optional :: line_col Line context column Source Code subroutine file_parse_error ( error , file_name , message , line_num , & line_string , line_col ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Name of file character ( len =* ), intent ( in ) :: file_name !> Parse error message character ( len =* ), intent ( in ) :: message !> Line number of parse error integer , intent ( in ), optional :: line_num !> Line context string character ( len =* ), intent ( in ), optional :: line_string !> Line context column integer , intent ( in ), optional :: line_col character ( 50 ) :: temp_string allocate ( error ) error % message = 'Parse error: ' // message // new_line ( 'a' ) error % message = error % message // file_name if ( present ( line_num )) then write ( temp_string , '(I0)' ) line_num error % message = error % message // ':' // trim ( temp_string ) end if if ( present ( line_col )) then if ( line_col > 0 ) then write ( temp_string , '(I0)' ) line_col error % message = error % message // ':' // trim ( temp_string ) end if end if if ( present ( line_string )) then error % message = error % message // new_line ( 'a' ) error % message = error % message // ' | ' // line_string if ( present ( line_col )) then if ( line_col > 0 ) then error % message = error % message // new_line ( 'a' ) error % message = error % message // ' | ' // repeat ( ' ' , line_col - 1 ) // '^' end if end if end if end subroutine file_parse_error","tags":"","loc":"proc/file_parse_error.html"},{"title":"fpm_stop – Fortran-lang/fpm","text":"public subroutine fpm_stop(value, message) Arguments Type Intent Optional Attributes Name integer, intent(in) :: value value to use on STOP character(len=*), intent(in) :: message Error message Source Code subroutine fpm_stop ( value , message ) ! TODO: if verbose mode, call ERROR STOP instead of STOP ! TODO: if M_escape is used, add color ! to work with older compilers might need a case statement for values !> value to use on STOP integer , intent ( in ) :: value !> Error message character ( len =* ), intent ( in ) :: message integer :: iostat if ( message /= '' ) then flush ( unit = stderr , iostat = iostat ) flush ( unit = stdout , iostat = iostat ) if ( value > 0 ) then write ( stderr , '(\" \",a)' ) trim ( message ) else write ( stderr , '(\" \",a)' ) trim ( message ) endif flush ( unit = stderr , iostat = iostat ) endif stop value end subroutine fpm_stop","tags":"","loc":"proc/fpm_stop.html"},{"title":"syntax_error – Fortran-lang/fpm","text":"public subroutine syntax_error(error, message) Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: message Error message Source Code subroutine syntax_error ( error , message ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message character ( len =* ), intent ( in ) :: message allocate ( error ) error % message = message end subroutine syntax_error","tags":"","loc":"proc/syntax_error.html"},{"title":"fpm_version – Fortran-lang/fpm","text":"public function fpm_version() Return the current fpm version from fpm_version_ID as a version type Arguments None Return Value type( version_t ) Source Code type ( version_t ) function fpm_version () type ( error_t ), allocatable :: error ! Fallback to last known version in case of undefined macro #ifndef FPM_RELEASE_VERSION # define FPM_RELEASE_VERSION 0.10.1 #endif ! Accept solution from https://stackoverflow.com/questions/31649691/stringify-macro-with-gnu-gfortran ! which provides the \"easiest\" way to pass a macro to a string in Fortran complying with both ! gfortran's \"traditional\" cpp and the standard cpp syntaxes #ifdef __GFORTRAN__ /* traditional-cpp stringification */ # define STRINGIFY_START(X) \"& # define STRINGIFY_END(X) &X\" #else /* default stringification */ # define STRINGIFY_(X) #X # define STRINGIFY_START(X) & # define STRINGIFY_END(X) STRINGIFY_(X) #endif character ( len = :), allocatable :: ver_string ver_string = STRINGIFY_START ( FPM_RELEASE_VERSION ) STRINGIFY_END ( FPM_RELEASE_VERSION ) call new_version ( fpm_version , ver_string , error ) if ( allocated ( error )) call fpm_stop ( 1 , '*fpm*:internal error: cannot get version - ' // error % message ) end function fpm_version","tags":"","loc":"proc/fpm_version.html"},{"title":"new_test – Fortran-lang/fpm","text":"public subroutine new_test(self, table, error) Construct a new test configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( test_config_t ), intent(out) :: self Instance of the test configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_test ( self , table , error ) !> Instance of the test configuration type ( test_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve test name\" ) return end if if ( bad_name_error ( error , 'test' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"test\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_test","tags":"","loc":"proc/new_test.html"},{"title":"MPI_TYPE_NAME – Fortran-lang/fpm","text":"public pure function MPI_TYPE_NAME(mpilib) result(name) Return a name for the MPI library Arguments Type Intent Optional Attributes Name integer, intent(in) :: mpilib Return Value character(len=:), allocatable Source Code pure function MPI_TYPE_NAME ( mpilib ) result ( name ) integer , intent ( in ) :: mpilib character ( len = :), allocatable :: name select case ( mpilib ) case ( MPI_TYPE_NONE ); name = \"none\" case ( MPI_TYPE_OPENMPI ); name = \"OpenMPI\" case ( MPI_TYPE_MPICH ); name = \"MPICH\" case ( MPI_TYPE_INTEL ); name = \"INTELMPI\" case ( MPI_TYPE_MSMPI ); name = \"MS-MPI\" case default ; name = \"UNKNOWN\" end select end function MPI_TYPE_NAME","tags":"","loc":"proc/mpi_type_name.html"},{"title":"resolve_metapackages – Fortran-lang/fpm","text":"public interface resolve_metapackages Module Procedures private subroutine resolve_metapackage_model(model, package, settings, error) Resolve all metapackages into the package config Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(inout) :: model type( package_config_t ), intent(inout) :: package class( fpm_build_settings ), intent(inout) :: settings type( error_t ), intent(out), allocatable :: error","tags":"","loc":"interface/resolve_metapackages.html"},{"title":"dilate – Fortran-lang/fpm","text":"public function dilate(instr) result(outstr) NAME dilate(3f) - [M_strings:NONALPHA] expand tab characters\n(LICENSE:PD) SYNOPSIS function dilate(INSTR) result ( OUTSTR ) character ( len = * ), intent =( in ) :: INSTR character ( len =:), allocatable :: OUTSTR DESCRIPTION dilate() converts tabs in INSTR to spaces in OUTSTR. It assumes a\n tab is set every 8 characters. Trailing spaces are removed.\n\n In addition, trailing carriage returns and line feeds are removed\n (they are usually a problem created by going to and from MSWindows). OPTIONS instr Input line to remove tabs from RESULTS outstr Output string with tabs expanded. EXAMPLES Sample program: program demo_dilate use M_strings , only : dilate implicit none character ( len =:), allocatable :: in integer :: i in = ' this is my string ' ! change spaces to tabs to make a sample input do i = 1 , len ( in ) if ( in ( i : i ) == ' ' ) in ( i : i )= char ( 9 ) enddo write ( * , ' ( a ) ' ) in , dilate ( in ) end program demo_dilate Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: instr Return Value character(len=:), allocatable Source Code function dilate ( instr ) result ( outstr ) character ( len =* ), intent ( in ) :: instr ! input line to scan for tab characters character ( len = :), allocatable :: outstr ! tab-expanded version of INSTR produced integer :: i integer :: icount integer :: lgth icount = 0 do i = 1 , len ( instr ) if ( instr ( i : i ) == char ( 9 )) icount = icount + 1 end do allocate ( character ( len = ( len ( instr ) + 8 * icount )) :: outstr ) call notabs ( instr , outstr , lgth ) outstr = outstr (: lgth ) end function dilate","tags":"","loc":"proc/dilate.html"},{"title":"f_string – Fortran-lang/fpm","text":"public function f_string(c_string) Uses iso_c_binding return Fortran character variable when given a C-like array of\nsingle characters terminated with a C_NULL_CHAR character Arguments Type Intent Optional Attributes Name character(len=1), intent(in) :: c_string (:) Return Value character(len=:), allocatable Source Code function f_string ( c_string ) use iso_c_binding character ( len = 1 ), intent ( in ) :: c_string (:) character (:), allocatable :: f_string integer :: i , n i = 0 do while ( c_string ( i + 1 ) /= C_NULL_CHAR ) i = i + 1 end do n = i allocate ( character ( n ) :: f_string ) do i = 1 , n f_string ( i : i ) = c_string ( i ) end do end function f_string","tags":"","loc":"proc/f_string.html"},{"title":"glob – Fortran-lang/fpm","text":"public function glob(tame, wild) NAME glob(3f) - [fpm_strings:COMPARE] compare given string for match to\npattern which may contain wildcard characters\n(LICENSE:PD) SYNOPSIS logical function glob(string, pattern )\n\n character(len=*),intent(in) :: string\n character(len=*),intent(in) :: pattern DESCRIPTION glob(3f) compares given STRING for match to PATTERN which may\n contain wildcard characters. In this version to get a match the entire string must be described\n by PATTERN. Trailing whitespace is significant, so trim the input\n string to have trailing whitespace ignored. OPTIONS string the input string to test to see if it contains the pattern . pattern the following simple globbing options are available o \"?\" matching any one character o \"*\" matching zero or more characters . Do NOT use adjacent asterisks . o Both strings may have trailing spaces which are ignored . o There is no escape character , so matching strings with literal question mark and asterisk is problematic . EXAMPLES Example program program demo_glob implicit none ! This main () routine passes a bunch of test strings ! into the above code . In performance comparison mode , ! it does that over and over . Otherwise , it does it just ! once . Either way , it outputs a passed / failed result . ! integer :: nReps logical :: allpassed integer :: i allpassed = . true . nReps = 10000 ! Can choose as many repetitions as you ' re expecting ! in the real world . nReps = 1 do i = 1 , nReps ! Cases with repeating character sequences . allpassed = allpassed . and . test ( \"a*abab\" , \"a*b\" , . true .) !! cycle allpassed = allpassed . and . test ( \"ab\" , \"*?\" , . true .) allpassed = allpassed . and . test ( \"abc\" , \"*?\" , . true .) allpassed = allpassed . and . test ( \"abcccd\" , \"*ccd\" , . true .) allpassed = allpassed . and . test ( \"bLah\" , \"bLaH\" , . false .) allpassed = allpassed . and . test ( \"mississippi\" , \"*sip*\" , . true .) allpassed = allpassed . and . & & test ( \"xxxx*zzzzzzzzy*f\" , \"xxx*zzy*f\" , . true .) allpassed = allpassed . and . & & test ( \"xxxx*zzzzzzzzy*f\" , \"xxxx*zzy*fffff\" , . false .) allpassed = allpassed . and . & & test ( \"mississipissippi\" , \"*issip*ss*\" , . true .) allpassed = allpassed . and . & & test ( \"xxxxzzzzzzzzyf\" , \"xxxx*zzy*fffff\" , . false .) allpassed = allpassed . and . & & test ( \"xxxxzzzzzzzzyf\" , \"xxxx*zzy*f\" , . true .) allpassed = allpassed . and . test ( \"xyxyxyzyxyz\" , \"xy*z*xyz\" , . true .) allpassed = allpassed . and . test ( \"xyxyxyxyz\" , \"xy*xyz\" , . true .) allpassed = allpassed . and . test ( \"mississippi\" , \"mi*sip*\" , . true .) allpassed = allpassed . and . test ( \"ababac\" , \"*abac*\" , . true .) allpassed = allpassed . and . test ( \"aaazz\" , \"a*zz*\" , . true .) allpassed = allpassed . and . test ( \"a12b12\" , \"*12*23\" , . false .) allpassed = allpassed . and . test ( \"a12b12\" , \"a12b\" , . false .) allpassed = allpassed . and . test ( \"a12b12\" , \"*12*12*\" , . true .) ! Additional cases where the '*' char appears in the tame string . allpassed = allpassed . and . test ( \"*\" , \"*\" , . true .) allpassed = allpassed . and . test ( \"a*r\" , \"a*\" , . true .) allpassed = allpassed . and . test ( \"a*ar\" , \"a*aar\" , . false .) ! More double wildcard scenarios . allpassed = allpassed . and . test ( \"XYXYXYZYXYz\" , \"XY*Z*XYz\" , . true .) allpassed = allpassed . and . test ( \"missisSIPpi\" , \"*SIP*\" , . true .) allpassed = allpassed . and . test ( \"mississipPI\" , \"*issip*PI\" , . true .) allpassed = allpassed . and . test ( \"xyxyxyxyz\" , \"xy*xyz\" , . true .) allpassed = allpassed . and . test ( \"miSsissippi\" , \"mi*sip*\" , . true .) allpassed = allpassed . and . test ( \"miSsissippi\" , \"mi*Sip*\" , . false .) allpassed = allpassed . and . test ( \"abAbac\" , \"*Abac*\" , . true .) allpassed = allpassed . and . test ( \"aAazz\" , \"a*zz*\" , . true .) allpassed = allpassed . and . test ( \"A12b12\" , \"*12*23\" , . false .) allpassed = allpassed . and . test ( \"a12B12\" , \"*12*12*\" , . true .) allpassed = allpassed . and . test ( \"oWn\" , \"*oWn*\" , . true .) ! Completely tame ( no wildcards ) cases . allpassed = allpassed . and . test ( \"bLah\" , \"bLah\" , . true .) ! Simple mixed wildcard tests suggested by IBMer Marlin Deckert . allpassed = allpassed . and . test ( \"a\" , \"*?\" , . true .) ! More mixed wildcard tests including coverage for false positives . allpassed = allpassed . and . test ( \"a\" , \"??\" , . false .) allpassed = allpassed . and . test ( \"ab\" , \"?*?\" , . true .) allpassed = allpassed . and . test ( \"ab\" , \"*?*?*\" , . true .) allpassed = allpassed . and . test ( \"abc\" , \"?**?*?\" , . true .) allpassed = allpassed . and . test ( \"abc\" , \"?**?*&?\" , . false .) allpassed = allpassed . and . test ( \"abcd\" , \"?b*??\" , . true .) allpassed = allpassed . and . test ( \"abcd\" , \"?a*??\" , . false .) allpassed = allpassed . and . test ( \"abcd\" , \"?**?c?\" , . true .) allpassed = allpassed . and . test ( \"abcd\" , \"?**?d?\" , . false .) allpassed = allpassed . and . test ( \"abcde\" , \"?*b*?*d*?\" , . true .) ! Single - character - match cases . allpassed = allpassed . and . test ( \"bLah\" , \"bL?h\" , . true .) allpassed = allpassed . and . test ( \"bLaaa\" , \"bLa?\" , . false .) allpassed = allpassed . and . test ( \"bLah\" , \"bLa?\" , . true .) allpassed = allpassed . and . test ( \"bLaH\" , \"?Lah\" , . false .) allpassed = allpassed . and . test ( \"bLaH\" , \"?LaH\" , . true .) ! Many - wildcard scenarios . allpassed = allpassed . and . test ( & & \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa& &aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab\" , & & \"a*a*a*a*a*a*aa*aaa*a*a*b\" , & & . true .) allpassed = allpassed . and . test ( & & \"abababababababababababababababababababaacacacacacacac& &adaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\" , & & \"*a*b*ba*ca*a*aa*aaa*fa*ga*b*\" , & & . true .) allpassed = allpassed . and . test ( & & \"abababababababababababababababababababaacacacacacaca& &cadaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\" , & & \"*a*b*ba*ca*a*x*aaa*fa*ga*b*\" , & & . false .) allpassed = allpassed . and . test ( & & \"abababababababababababababababababababaacacacacacacacad& &aeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\" , & & \"*a*b*ba*ca*aaaa*fa*ga*gggg*b*\" , & & . false .) allpassed = allpassed . and . test ( & & \"abababababababababababababababababababaacacacacacacacad& &aeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\" , & & \"*a*b*ba*ca*aaaa*fa*ga*ggg*b*\" , & & . true .) allpassed = allpassed . and . test ( \"aaabbaabbaab\" , \"*aabbaa*a*\" , . true .) allpassed = allpassed . and . & test ( \"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\" , & & \"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\" , . true .) allpassed = allpassed . and . test ( \"aaaaaaaaaaaaaaaaa\" , & & \"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\" , . true .) allpassed = allpassed . and . test ( \"aaaaaaaaaaaaaaaa\" , & & \"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\" , . false .) allpassed = allpassed . and . test ( & & \"abc*abcd*abcde*abcdef*abcdefg*abcdefgh*abcdefghi*abcdefghij& &*abcdefghijk*abcdefghijkl*abcdefghijklm*abcdefghijklmn\" , & & \"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc& &*abc*abc*abc*\" , & & . false .) allpassed = allpassed . and . test ( & & \"abc*abcd*abcde*abcdef*abcdefg*abcdefgh*abcdefghi*abcdefghij& &*abcdefghijk*abcdefghijkl*abcdefghijklm*abcdefghijklmn\" , & & \"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*\" , & & . true .) allpassed = allpassed . and . test ( \"abc*abcd*abcd*abc*abcd\" , & & \"abc*abc*abc*abc*abc\" , . false .) allpassed = allpassed . and . test ( \"abc*abcd*abcd*abc*abcd*abcd& &*abc*abcd*abc*abc*abcd\" , & & \"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abcd\" , & & . true .) allpassed = allpassed . and . test ( \"abc\" , & & \"********a********b********c********\" , . true .) allpassed = allpassed . and . & & test ( \"********a********b********c********\" , \"abc\" , . false .) allpassed = allpassed . and . & & test ( \"abc\" , \"********a********b********b********\" , . false .) allpassed = allpassed . and . test ( \"*abc*\" , \"***a*b*c***\" , . true .) ! A case - insensitive algorithm test . ! allpassed = allpassed . and . test ( \"mississippi\" , \"*issip*PI\" , . true .) enddo if ( allpassed ) then write ( * , ' ( a ) ' ) \"Passed\" , nReps else write ( * , ' ( a ) ' ) \"Failed\" endif contains ! This is a test program for wildcard matching routines . ! It can be used either to test a single routine for correctness , ! or to compare the timings of two ( or more ) different wildcard ! matching routines . ! function test ( tame , wild , bExpectedResult ) result ( bpassed ) use fpm_strings , only : glob character ( len = * ) :: tame character ( len = * ) :: wild logical :: bExpectedResult logical :: bResult logical :: bPassed bResult = . true . ! We ' ll do \"&=\" cumulative checking . bPassed = . false . ! Assume the worst . write ( * , * ) repeat ( '=' , 79 ) bResult = glob ( tame , wild ) ! Call a wildcard matching routine . ! To assist correctness checking , output the two strings in any ! failing scenarios . if ( bExpectedResult . eqv . bResult ) then bPassed = . true . if ( nReps == 1 ) write ( * , * ) \"Passed match on \" , tame , \" vs. \" , wild else if ( nReps == 1 ) write ( * , * ) \"Failed match on \" , tame , \" vs. \" , wild endif end function test end program demo_glob Expected output REFERENCE The article “Matching Wildcards: An Empirical Way to Tame an Algorithm”\n in Dr Dobb’s Journal, By Kirk J. Krauss, October 07, 2014 Arguments Type Intent Optional Attributes Name character(len=*) :: tame A string without wildcards to compare to the globbing expression character(len=*) :: wild A (potentially) corresponding string with wildcards Return Value logical result of test Source Code function glob ( tame , wild ) ! @(#)fpm_strings::glob(3f): function compares text strings, one of which can have wildcards ('*' or '?'). logical :: glob !! result of test character ( len =* ) :: tame !! A string without wildcards to compare to the globbing expression character ( len =* ) :: wild !! A (potentially) corresponding string with wildcards character ( len = len ( tame ) + 1 ) :: tametext character ( len = len ( wild ) + 1 ) :: wildtext character ( len = 1 ), parameter :: NULL = char ( 0 ) integer :: wlen integer :: ti , wi integer :: i character ( len = :), allocatable :: tbookmark , wbookmark ! These two values are set when we observe a wildcard character. They ! represent the locations, in the two strings, from which we start once we've observed it. tametext = tame // NULL wildtext = wild // NULL tbookmark = NULL wbookmark = NULL wlen = len ( wild ) wi = 1 ti = 1 do ! Walk the text strings one character at a time. if ( wildtext ( wi : wi ) == '*' ) then ! How do you match a unique text string? do i = wi , wlen ! Easy: unique up on it! if ( wildtext ( wi : wi ) == '*' ) then wi = wi + 1 else exit endif enddo if ( wildtext ( wi : wi ) == NULL ) then ! \"x\" matches \"*\" glob = . true . return endif if ( wildtext ( wi : wi ) /= '?' ) then ! Fast-forward to next possible match. do while ( tametext ( ti : ti ) /= wildtext ( wi : wi )) ti = ti + 1 if ( tametext ( ti : ti ) == NULL ) then glob = . false . return ! \"x\" doesn't match \"*y*\" endif enddo endif wbookmark = wildtext ( wi :) tbookmark = tametext ( ti :) elseif ( tametext ( ti : ti ) /= wildtext ( wi : wi ) . and . wildtext ( wi : wi ) /= '?' ) then ! Got a non-match. If we've set our bookmarks, back up to one or both of them and retry. if ( wbookmark /= NULL ) then if ( wildtext ( wi :) /= wbookmark ) then wildtext = wbookmark ; wlen = len_trim ( wbookmark ) wi = 1 ! Don't go this far back again. if ( tametext ( ti : ti ) /= wildtext ( wi : wi )) then tbookmark = tbookmark ( 2 :) tametext = tbookmark ti = 1 cycle ! \"xy\" matches \"*y\" else wi = wi + 1 endif endif if ( tametext ( ti : ti ) /= NULL ) then ti = ti + 1 cycle ! \"mississippi\" matches \"*sip*\" endif endif glob = . false . return ! \"xy\" doesn't match \"x\" endif ti = ti + 1 wi = wi + 1 if ( tametext ( ti : ti ) == NULL ) then ! How do you match a tame text string? if ( wildtext ( wi : wi ) /= NULL ) then do while ( wildtext ( wi : wi ) == '*' ) ! The tame way: unique up on it! wi = wi + 1 ! \"x\" matches \"x*\" if ( wildtext ( wi : wi ) == NULL ) exit enddo endif if ( wildtext ( wi : wi ) == NULL ) then glob = . true . return ! \"x\" matches \"x\" endif glob = . false . return ! \"x\" doesn't match \"xy\" endif enddo end function glob","tags":"","loc":"proc/glob.html"},{"title":"has_valid_custom_prefix – Fortran-lang/fpm","text":"public function has_valid_custom_prefix(module_name, custom_prefix) result(valid) Check that a module name is prefixed with a custom prefix:\n1) It must be a valid FORTRAN name subset (<=63 chars, begin with letter, only alphanumeric allowed)\n2) It must begin with the prefix\n3) If longer, package name must be followed by default separator (“_”) plus at least one char Basic check: check that both names are individually valid FPM package enforcing: check that the module name begins with the custom prefix Query string lengths\n2) It must begin with the package name.\n3) It can be equal to the package name, or, if longer, must be followed by the\n4) Package name must not end with an underscore Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: custom_prefix Return Value logical Source Code logical function has_valid_custom_prefix ( module_name , custom_prefix ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: custom_prefix !> custom_module separator: single underscore character ( * ), parameter :: SEP = \"_\" logical :: is_same , has_separator , same_beginning integer :: lpkg , lmod , lsep !> Basic check: check that both names are individually valid valid = is_fortran_name ( module_name % s ) . and . & is_valid_module_prefix ( custom_prefix ) !> FPM package enforcing: check that the module name begins with the custom prefix if ( valid ) then !> Query string lengths lpkg = len_trim ( custom_prefix ) lmod = len_trim ( module_name ) lsep = len_trim ( SEP ) same_beginning = str_begins_with_str ( module_name % s , custom_prefix % s , case_sensitive = . false .) is_same = lpkg == lmod . and . same_beginning if ( lmod >= lpkg + lsep ) then has_separator = str_begins_with_str ( module_name % s ( lpkg + 1 : lpkg + lsep ), SEP ) else has_separator = . false . endif !> 2) It must begin with the package name. !> 3) It can be equal to the package name, or, if longer, must be followed by the ! default separator plus at least one character !> 4) Package name must not end with an underscore valid = same_beginning . and . ( is_same . or . ( lmod > lpkg + lsep . and . has_separator )) end if end function has_valid_custom_prefix","tags":"","loc":"proc/has_valid_custom_prefix.html"},{"title":"has_valid_standard_prefix – Fortran-lang/fpm","text":"public function has_valid_standard_prefix(module_name, package_name) result(valid) Check that a module name is prefixed with the default package prefix:\n1) It must be a valid FORTRAN name (<=63 chars, begin with letter, “_” is only allowed non-alphanumeric)\n2) It must begin with the package name\n3) If longer, package name must be followed by default separator plus at least one char Basic check: check the name is Fortran-compliant FPM package enforcing: check that the module name begins with the package name Query string lengths\n2) It must begin with the package name.\n3) It can be equal to the package name, or, if longer, must be followed by the\n4) Package name must not end with an underscore Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: package_name Return Value logical Source Code logical function has_valid_standard_prefix ( module_name , package_name ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: package_name !> Default package__module separator: two underscores character ( * ), parameter :: SEP = \"__\" character ( len = :), allocatable :: fortranized_pkg logical :: is_same , has_separator , same_beginning integer :: lpkg , lmod , lsep !> Basic check: check the name is Fortran-compliant valid = is_fortran_name ( module_name % s ) !> FPM package enforcing: check that the module name begins with the package name if ( valid ) then fortranized_pkg = to_fortran_name ( package_name % s ) !> Query string lengths lpkg = len_trim ( fortranized_pkg ) lmod = len_trim ( module_name ) lsep = len_trim ( SEP ) same_beginning = str_begins_with_str ( module_name % s , fortranized_pkg , case_sensitive = . false .) is_same = lpkg == lmod . and . same_beginning if ( lmod >= lpkg + lsep ) then has_separator = str_begins_with_str ( module_name % s ( lpkg + 1 : lpkg + lsep ), SEP ) else has_separator = . false . endif !> 2) It must begin with the package name. !> 3) It can be equal to the package name, or, if longer, must be followed by the ! default separator plus at least one character !> 4) Package name must not end with an underscore valid = is_fortran_name ( fortranized_pkg ) . and . & fortranized_pkg ( lpkg : lpkg ) /= '_' . and . & ( same_beginning . and . ( is_same . or . ( lmod > lpkg + lsep . and . has_separator ))) end if end function has_valid_standard_prefix","tags":"","loc":"proc/has_valid_standard_prefix.html"},{"title":"is_fortran_name – Fortran-lang/fpm","text":"public elemental function is_fortran_name(line) result(lout) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: line Return Value logical Source Code elemental function is_fortran_name ( line ) result ( lout ) ! determine if a string is a valid Fortran name ignoring trailing spaces ! (but not leading spaces) character ( len =* ), parameter :: int = '0123456789' character ( len =* ), parameter :: lower = 'abcdefghijklmnopqrstuvwxyz' character ( len =* ), parameter :: upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' character ( len =* ), parameter :: allowed = upper // lower // int // '_' character ( len =* ), intent ( in ) :: line character ( len = :), allocatable :: name logical :: lout name = trim ( line ) if ( len ( name ) /= 0 ) then lout = . true . & & . and . verify ( name ( 1 : 1 ), lower // upper ) == 0 & & . and . verify ( name , allowed ) == 0 & & . and . len ( name ) <= 63 else lout = . false . endif end function is_fortran_name","tags":"","loc":"proc/is_fortran_name.html"},{"title":"is_valid_module_name – Fortran-lang/fpm","text":"public function is_valid_module_name(module_name, package_name, custom_prefix, enforce_module_names) result(valid) Check that a module name fits the current naming rules:\n1) It must be a valid FORTRAN name (<=63 chars, begin with letter, “_” is only allowed non-alphanumeric)\n2) It must begin with the package name\n3) If longer, package name must be followed by default separator plus at least one char Basic check: check the name is Fortran-compliant FPM package enforcing: check that the module name begins with the package name Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: package_name type( string_t ), intent(in) :: custom_prefix logical, intent(in) :: enforce_module_names Return Value logical Source Code logical function is_valid_module_name ( module_name , package_name , custom_prefix , enforce_module_names ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: package_name type ( string_t ), intent ( in ) :: custom_prefix logical , intent ( in ) :: enforce_module_names !> Basic check: check the name is Fortran-compliant valid = is_fortran_name ( module_name % s ); if (. not . valid ) return !> FPM package enforcing: check that the module name begins with the package name if ( enforce_module_names ) then ! Default prefixing is always valid valid = has_valid_standard_prefix ( module_name , package_name ) ! If a custom prefix was validated, it provides additional naming options ! Because they never overlap with the default prefix, the former is always an option if ( len_trim ( custom_prefix ) > 0 . and . . not . valid ) & valid = has_valid_custom_prefix ( module_name , custom_prefix ) end if end function is_valid_module_name","tags":"","loc":"proc/is_valid_module_name.html"},{"title":"is_valid_module_prefix – Fortran-lang/fpm","text":"public function is_valid_module_prefix(module_prefix) result(valid) Check that a custom module prefix fits the current naming rules:\n1) Only alphanumeric characters (no spaces, dashes, underscores or other characters)\n2) Does not begin with a number (Fortran-compatible syntax) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_prefix Return Value logical Source Code logical function is_valid_module_prefix ( module_prefix ) result ( valid ) type ( string_t ), intent ( in ) :: module_prefix character ( len =* ), parameter :: num = '0123456789' character ( len =* ), parameter :: lower = 'abcdefghijklmnopqrstuvwxyz' character ( len =* ), parameter :: upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' character ( len =* ), parameter :: alpha = upper // lower character ( len =* ), parameter :: allowed = alpha // num character ( len = :), allocatable :: name name = trim ( module_prefix % s ) if ( len ( name ) > 0 . and . len ( name ) <= 63 ) then valid = verify ( name ( 1 : 1 ), alpha ) == 0 . and . & verify ( name , allowed ) == 0 else valid = . false . endif end function is_valid_module_prefix","tags":"","loc":"proc/is_valid_module_prefix.html"},{"title":"join – Fortran-lang/fpm","text":"public pure function join(str, sep, trm, left, right, start, end) result(string) NAME join ( 3 f ) - [ M_strings : EDITING ] append CHARACTER variable array into a single CHARACTER variable with specified separator ( LICENSE : PD ) SYNOPSIS pure function join(str,sep,trm,left,right,start,end) result (string)\n\n character(len=*),intent(in) :: str(:)\n character(len=*),intent(in),optional :: sep\n logical,intent(in),optional :: trm\n character(len=*),intent(in),optional :: right\n character(len=*),intent(in),optional :: left\n character(len=*),intent(in),optional :: start\n character(len=*),intent(in),optional :: end\n character(len=:),allocatable :: string DESCRIPTION JOIN(3f) appends the elements of a CHARACTER array into a single\n CHARACTER variable, with elements 1 to N joined from left to right.\n By default each element is trimmed of trailing spaces and the\n default separator is a null string. OPTIONS STR (:) array of CHARACTER variables to be joined SEP separator string to place between each variable . defaults to a null string . LEFT string to place at left of each element RIGHT string to place at right of each element START prefix string END suffix string TRM option to trim each element of STR of trailing spaces . Defaults to . TRUE . RESULT STRING CHARACTER variable composed of all of the elements of STR () appended together with the optional separator SEP placed between the elements . EXAMPLE Sample program: program demo_join\n use M_strings, only: join\n implicit none\n character(len=:),allocatable :: s(:)\n character(len=:),allocatable :: out\n integer :: i\n s=[character(len=10) :: ‘United’,’ we’,’ stand,’, &\n & ’ divided’,’ we fall.’]\n out=join(s)\n write( ,’(a)’) out\n write( ,’(a)’) join(s,trm=.false.)\n write( ,’(a)’) (join(s,trm=.false.,sep=’|’),i=1,3)\n write( ,’(a)’) join(s,sep=’<>’)\n write( ,’(a)’) join(s,sep=’;’,left=’[‘,right=’]’)\n write( ,’(a)’) join(s,left=’[‘,right=’]’)\n write(*,’(a)’) join(s,left=’>>’)\n end program demo_join Expected output: United we stand, divided we fall.\n United we stand, divided we fall.\n United | we | stand, | divided | we fall.\n United | we | stand, | divided | we fall.\n United | we | stand, | divided | we fall.\n United<> we<> stand,<> divided<> we fall.\n [United];[ we];[ stand,];[ divided];[ we fall.]\n [United][ we][ stand,][ divided][ we fall.] United>> we>> stand,>> divided>> we fall. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str (:) character(len=*), intent(in), optional :: sep logical, intent(in), optional :: trm character(len=*), intent(in), optional :: left character(len=*), intent(in), optional :: right character(len=*), intent(in), optional :: start character(len=*), intent(in), optional :: end Return Value character(len=:), allocatable Source Code pure function join ( str , sep , trm , left , right , start , end ) result ( string ) ! @(#)M_strings::join(3f): merge string array into a single CHARACTER value adding specified separators, caps, prefix and suffix character ( len =* ), intent ( in ) :: str (:) character ( len =* ), intent ( in ), optional :: sep , right , left , start , end logical , intent ( in ), optional :: trm character ( len = :), allocatable :: sep_local , left_local , right_local character ( len = :), allocatable :: string logical :: trm_local integer :: i if ( present ( sep )) then ; sep_local = sep ; else ; sep_local = '' ; endif if ( present ( trm )) then ; trm_local = trm ; else ; trm_local = . true . ; endif if ( present ( left )) then ; left_local = left ; else ; left_local = '' ; endif if ( present ( right )) then ; right_local = right ; else ; right_local = '' ; endif string = '' if ( size ( str ) == 0 ) then string = string // left_local // right_local else do i = 1 , size ( str ) - 1 if ( trm_local ) then string = string // left_local // trim ( str ( i )) // right_local // sep_local else string = string // left_local // str ( i ) // right_local // sep_local endif enddo if ( trm_local ) then string = string // left_local // trim ( str ( i )) // right_local else string = string // left_local // str ( i ) // right_local endif endif if ( present ( start )) string = start // string if ( present ( end )) string = string // end end function join","tags":"","loc":"proc/join.html"},{"title":"lower – Fortran-lang/fpm","text":"public pure elemental function lower(str, begin, end) result(string) Changes a string to lowercase over optional specified column range Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str integer, intent(in), optional :: begin integer, intent(in), optional :: end Return Value character(len=len(str)) Source Code elemental pure function lower ( str , begin , end ) result ( string ) character ( * ), intent ( In ) :: str character ( len ( str )) :: string integer , intent ( in ), optional :: begin , end integer :: i integer :: ibegin , iend string = str ibegin = 1 if ( present ( begin )) then ibegin = max ( ibegin , begin ) endif iend = len_trim ( str ) if ( present ( end )) then iend = min ( iend , end ) endif do i = ibegin , iend ! step thru each letter in the string in specified range select case ( str ( i : i )) case ( 'A' : 'Z' ) string ( i : i ) = char ( iachar ( str ( i : i )) + 32 ) ! change letter to miniscule case default end select end do end function lower","tags":"","loc":"proc/lower.html"},{"title":"module_prefix_template – Fortran-lang/fpm","text":"public function module_prefix_template(project_name, custom_prefix) result(prefix) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: project_name type( string_t ), intent(in) :: custom_prefix Return Value type( string_t ) Source Code type ( string_t ) function module_prefix_template ( project_name , custom_prefix ) result ( prefix ) type ( string_t ), intent ( in ) :: project_name type ( string_t ), intent ( in ) :: custom_prefix if ( is_valid_module_prefix ( custom_prefix )) then prefix = string_t ( trim ( custom_prefix % s ) // \"_\" ) else prefix = string_t ( to_fortran_name ( project_name % s ) // \"__\" ) end if end function module_prefix_template","tags":"","loc":"proc/module_prefix_template.html"},{"title":"module_prefix_type – Fortran-lang/fpm","text":"public function module_prefix_type(project_name, custom_prefix) result(ptype) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: project_name type( string_t ), intent(in) :: custom_prefix Return Value type( string_t ) Source Code type ( string_t ) function module_prefix_type ( project_name , custom_prefix ) result ( ptype ) type ( string_t ), intent ( in ) :: project_name type ( string_t ), intent ( in ) :: custom_prefix if ( is_valid_module_prefix ( custom_prefix )) then ptype = string_t ( \"custom\" ) else ptype = string_t ( \"default\" ) end if end function module_prefix_type","tags":"","loc":"proc/module_prefix_type.html"},{"title":"replace – Fortran-lang/fpm","text":"public pure function replace(string, charset, target_char) result(res) Returns string with characters in charset replaced with target_char. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string character(len=1), intent(in) :: charset (:) character(len=1), intent(in) :: target_char Return Value character(len=len(string)) Source Code pure function replace ( string , charset , target_char ) result ( res ) character ( * ), intent ( in ) :: string character , intent ( in ) :: charset (:), target_char character ( len ( string )) :: res integer :: n res = string do n = 1 , len ( string ) if ( any ( string ( n : n ) == charset )) then res ( n : n ) = target_char end if end do end function replace","tags":"","loc":"proc/replace.html"},{"title":"str_begins_with_str – Fortran-lang/fpm","text":"public pure function str_begins_with_str(s, e, case_sensitive) result(r) test if a CHARACTER string begins with a specified prefix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e logical, intent(in), optional :: case_sensitive Return Value logical Source Code pure logical function str_begins_with_str ( s , e , case_sensitive ) result ( r ) character ( * ), intent ( in ) :: s , e logical , optional , intent ( in ) :: case_sensitive ! Default option: case sensitive integer :: n1 , n2 logical :: lower_case ! Check if case sensitive if ( present ( case_sensitive )) then lower_case = . not . case_sensitive else lower_case = . false . end if n1 = 1 n2 = 1 + len ( e ) - 1 if ( n2 > len ( s )) then r = . false . elseif ( lower_case ) then r = lower ( s ( n1 : n2 )) == lower ( e ) else r = ( s ( n1 : n2 ) == e ) end if end function str_begins_with_str","tags":"","loc":"proc/str_begins_with_str.html"},{"title":"string_array_contains – Fortran-lang/fpm","text":"public function string_array_contains(search_string, array) Check if array of TYPE(STRING_T) matches a particular CHARACTER string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: search_string type( string_t ), intent(in) :: array (:) Return Value logical Source Code logical function string_array_contains ( search_string , array ) character ( * ), intent ( in ) :: search_string type ( string_t ), intent ( in ) :: array (:) integer :: i string_array_contains = any ([( array ( i )% s == search_string , & i = 1 , size ( array ))]) end function string_array_contains","tags":"","loc":"proc/string_array_contains.html"},{"title":"string_cat – Fortran-lang/fpm","text":"public function string_cat(strings, delim) result(cat) Concatenate an array of type(string_t) into\n a single CHARACTER variable Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: strings (:) character(len=*), intent(in), optional :: delim Return Value character(len=:), allocatable Source Code function string_cat ( strings , delim ) result ( cat ) type ( string_t ), intent ( in ) :: strings (:) character ( * ), intent ( in ), optional :: delim character (:), allocatable :: cat integer :: i character (:), allocatable :: delim_str if ( size ( strings ) < 1 ) then cat = '' return end if if ( present ( delim )) then delim_str = delim else delim_str = '' end if cat = strings ( 1 )% s do i = 2 , size ( strings ) cat = cat // delim_str // strings ( i )% s end do end function string_cat","tags":"","loc":"proc/string_cat.html"},{"title":"to_fortran_name – Fortran-lang/fpm","text":"public pure function to_fortran_name(string) result(res) Returns string with special characters replaced with an underscore.\nFor now, only a hyphen is treated as a special character, but this can be\nexpanded to other characters if needed. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string Return Value character(len=len(string)) Source Code pure function to_fortran_name ( string ) result ( res ) character ( * ), intent ( in ) :: string character ( len ( string )) :: res character , parameter :: SPECIAL_CHARACTERS ( * ) = [ '-' ] res = replace ( string , SPECIAL_CHARACTERS , '_' ) end function to_fortran_name","tags":"","loc":"proc/to_fortran_name.html"},{"title":"upper – Fortran-lang/fpm","text":"public pure elemental function upper(str, begin, end) result(string) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str integer, intent(in), optional :: begin integer, intent(in), optional :: end Return Value character(len=len(str)) Source Code elemental pure function upper ( str , begin , end ) result ( string ) character ( * ), intent ( In ) :: str character ( len ( str )) :: string integer , intent ( in ), optional :: begin , end integer :: i integer :: ibegin , iend string = str ibegin = 1 if ( present ( begin )) then ibegin = max ( ibegin , begin ) endif iend = len_trim ( str ) if ( present ( end )) then iend = min ( iend , end ) endif do i = ibegin , iend ! step thru each letter in the string in specified range select case ( str ( i : i )) case ( 'a' : 'z' ) string ( i : i ) = char ( iachar ( str ( i : i )) - 32 ) ! change letter to capitalized case default end select end do end function upper","tags":"","loc":"proc/upper.html"},{"title":"notabs – Fortran-lang/fpm","text":"public impure elemental subroutine notabs(instr, outstr, ilen) NAME notabs(3f) - [fpm_strings:NONALPHA] expand tab characters\n (LICENSE:PD) SYNOPSIS subroutine notabs(INSTR,OUTSTR,ILEN)\n\n character(len=*),intent=(in) :: INSTR\n character(len=*),intent=(out) :: OUTSTR\n integer,intent=(out) :: ILEN DESCRIPTION NOTABS() converts tabs in INSTR to spaces in OUTSTR while maintaining\n columns. It assumes a tab is set every 8 characters. Trailing spaces\n are removed. In addition, trailing carriage returns and line feeds are removed\n (they are usually a problem created by going to and from MSWindows). What are some reasons for removing tab characters from an input line?\n Some Fortran compilers have problems with tabs, as tabs are not\n part of the Fortran character set. Some editors and printers will\n have problems with tabs. It is often useful to expand tabs in input\n files to simplify further processing such as tokenizing an input line. OPTIONS instr Input line to remove tabs from RESULTS outstr Output string with tabs expanded. Assumed to be of sufficient\n length\n ilen Significant length of returned string EXAMPLES Sample program: program demo_notabs\n\n! test filter to remove tabs and trailing white space from input\n! on files up to 1024 characters wide\nuse fpm_strings, only : notabs\ncharacter(len=1024) :: in,out\ninteger :: ios,iout\n do\n read(*,'(A)',iostat=ios)in\n if(ios /= 0) exit\n call notabs(in,out,iout)\n write(*,'(a)')out(:iout)\n enddo\nend program demo_notabs SEE ALSO GNU/Unix commands expand(1) and unexpand(1) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: instr character(len=*), intent(out) :: outstr integer, intent(out) :: ilen Source Code elemental impure subroutine notabs ( instr , outstr , ilen ) ! ident_31=\"@(#)fpm_strings::notabs(3f): convert tabs to spaces while maintaining columns, remove CRLF chars\" character ( len =* ), intent ( in ) :: instr ! input line to scan for tab characters character ( len =* ), intent ( out ) :: outstr ! tab-expanded version of INSTR produced integer , intent ( out ) :: ilen ! column position of last character put into output string ! that is, ILEN holds the position of the last non-blank character in OUTSTR integer , parameter :: tabsize = 8 ! assume a tab stop is set every 8th column integer :: ipos ! position in OUTSTR to put next character of INSTR integer :: lenin ! length of input string trimmed of trailing spaces integer :: lenout ! number of characters output string can hold integer :: istep ! counter that advances thru input string INSTR one character at a time character ( len = 1 ) :: c ! character in input line being processed integer :: iade ! ADE (ASCII Decimal Equivalent) of character being tested ipos = 1 ! where to put next character in output string OUTSTR lenin = len_trim ( instr ( 1 : len ( instr ) )) ! length of INSTR trimmed of trailing spaces lenout = len ( outstr ) ! number of characters output string OUTSTR can hold outstr = \" \" ! this SHOULD blank-fill string, a buggy machine required a loop to set all characters SCAN_LINE : do istep = 1 , lenin ! look through input string one character at a time c = instr ( istep : istep ) ! get next character iade = ichar ( c ) ! get ADE of the character EXPAND_TABS : select case ( iade ) ! take different actions depending on which character was found case ( 9 ) ! test if character is a tab and move pointer out to appropriate column ipos = ipos + ( tabsize - ( mod ( ipos - 1 , tabsize ))) case ( 10 , 13 ) ! convert carriage-return and new-line to space ,typically to handle DOS-format files ipos = ipos + 1 case default ! c is anything else other than a tab,newline,or return insert it in output string if ( ipos > lenout ) then write ( stderr , * ) \"*notabs* output string overflow\" exit else outstr ( ipos : ipos ) = c ipos = ipos + 1 endif end select EXPAND_TABS enddo SCAN_LINE ipos = min ( ipos , lenout ) ! tabs or newline or return characters or last character might have gone too far ilen = len_trim ( outstr (: ipos )) ! trim trailing spaces end subroutine notabs","tags":"","loc":"proc/notabs.html"},{"title":"remove_characters_in_set – Fortran-lang/fpm","text":"public subroutine remove_characters_in_set(string, set, replace_with) Arguments Type Intent Optional Attributes Name character(len=:), intent(inout), allocatable :: string character(len=*), intent(in) :: set character(len=1), intent(in), optional :: replace_with Source Code subroutine remove_characters_in_set ( string , set , replace_with ) character ( len = :), allocatable , intent ( inout ) :: string character ( * ), intent ( in ) :: set character , optional , intent ( in ) :: replace_with ! Replace with this character instead of removing integer :: feed , length if (. not . allocated ( string )) return if ( len ( set ) <= 0 ) return length = len ( string ) feed = scan ( string , set ) do while ( length > 0 . and . feed > 0 ) ! Remove heading if ( length == 1 ) then string = \"\" elseif ( feed == 1 ) then string = string ( 2 : length ) ! Remove trailing elseif ( feed == length ) then string = string ( 1 : length - 1 ) ! In between: replace with given character elseif ( present ( replace_with )) then string ( feed : feed ) = replace_with ! Or just remove else string = string ( 1 : feed - 1 ) // string ( feed + 1 : length ) end if length = len ( string ) feed = scan ( string , set ) end do end subroutine remove_characters_in_set","tags":"","loc":"proc/remove_characters_in_set.html"},{"title":"remove_newline_characters – Fortran-lang/fpm","text":"public subroutine remove_newline_characters(string) Arguments Type Intent Optional Attributes Name type( string_t ), intent(inout) :: string Source Code subroutine remove_newline_characters ( string ) type ( string_t ), intent ( inout ) :: string integer :: feed , length character ( * ), parameter :: CRLF = achar ( 13 ) // new_line ( 'a' ) character ( * ), parameter :: SPACE = ' ' call remove_characters_in_set ( string % s , set = CRLF , replace_with = SPACE ) end subroutine remove_newline_characters","tags":"","loc":"proc/remove_newline_characters.html"},{"title":"split – Fortran-lang/fpm","text":"public subroutine split(input_line, array, delimiters, order, nulls) parse string on delimiter characters and store tokens into an allocatable array\ngiven a line of structure ” par1 par2 par3 … parn ” store each par(n) into a separate variable in array. by default adjacent delimiters in the input string do not create an empty string in the output array no quoting of delimiters is supported Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: input_line input string to tokenize character(len=:), intent(out), allocatable :: array (:) output array of tokens character(len=*), intent(in), optional :: delimiters list of delimiter characters character(len=*), intent(in), optional :: order order of output array sequential|[reverse|right] character(len=*), intent(in), optional :: nulls return strings composed of delimiters or not ignore|return|ignoreend Source Code subroutine split ( input_line , array , delimiters , order , nulls ) !! given a line of structure \" par1 par2 par3 ... parn \" store each par(n) into a separate variable in array. !! !! * by default adjacent delimiters in the input string do not create an empty string in the output array !! * no quoting of delimiters is supported character ( len =* ), intent ( in ) :: input_line !! input string to tokenize character ( len =* ), optional , intent ( in ) :: delimiters !! list of delimiter characters character ( len =* ), optional , intent ( in ) :: order !! order of output array sequential|[reverse|right] character ( len =* ), optional , intent ( in ) :: nulls !! return strings composed of delimiters or not ignore|return|ignoreend character ( len = :), allocatable , intent ( out ) :: array (:) !! output array of tokens integer :: n ! max number of strings INPUT_LINE could split into if all delimiter integer , allocatable :: ibegin (:) ! positions in input string where tokens start integer , allocatable :: iterm (:) ! positions in input string where tokens end character ( len = :), allocatable :: dlim ! string containing delimiter characters character ( len = :), allocatable :: ordr ! string containing order keyword character ( len = :), allocatable :: nlls ! string containing nulls keyword integer :: ii , iiii ! loop parameters used to control print order integer :: icount ! number of tokens found integer :: ilen ! length of input string with trailing spaces trimmed integer :: i10 , i20 , i30 ! loop counters integer :: icol ! pointer into input string as it is being parsed integer :: idlim ! number of delimiter characters integer :: ifound ! where next delimiter character is found in remaining input string data integer :: inotnull ! count strings not composed of delimiters integer :: ireturn ! number of tokens returned integer :: imax ! length of longest token ! decide on value for optional DELIMITERS parameter if ( present ( delimiters )) then ! optional delimiter list was present if ( delimiters /= '' ) then ! if DELIMITERS was specified and not null use it dlim = delimiters else ! DELIMITERS was specified on call as empty string dlim = ' ' // char ( 9 ) // char ( 10 ) // char ( 11 ) // char ( 12 ) // char ( 13 ) // char ( 0 ) ! use default delimiter when not specified endif else ! no delimiter value was specified dlim = ' ' // char ( 9 ) // char ( 10 ) // char ( 11 ) // char ( 12 ) // char ( 13 ) // char ( 0 ) ! use default delimiter when not specified endif idlim = len ( dlim ) ! dlim a lot of blanks on some machines if dlim is a big string if ( present ( order )) then ; ordr = lower ( adjustl ( order )); else ; ordr = 'sequential' ; endif ! decide on value for optional ORDER parameter if ( present ( nulls )) then ; nlls = lower ( adjustl ( nulls )); else ; nlls = 'ignore' ; endif ! optional parameter n = len ( input_line ) + 1 ! max number of strings INPUT_LINE could split into if all delimiter allocate ( ibegin ( n )) ! allocate enough space to hold starting location of tokens if string all tokens allocate ( iterm ( n )) ! allocate enough space to hold ending location of tokens if string all tokens ibegin (:) = 1 iterm (:) = 1 ilen = len ( input_line ) ! ILEN is the column position of the last non-blank character icount = 0 ! how many tokens found inotnull = 0 ! how many tokens found not composed of delimiters imax = 0 ! length of longest token found select case ( ilen ) case ( 0 ) ! command was totally blank case default ! there is at least one non-delimiter in INPUT_LINE if get here icol = 1 ! initialize pointer into input line INFINITE : do i30 = 1 , ilen , 1 ! store into each array element ibegin ( i30 ) = icol ! assume start new token on the character if ( index ( dlim ( 1 : idlim ), input_line ( icol : icol )) == 0 ) then ! if current character is not a delimiter iterm ( i30 ) = ilen ! initially assume no more tokens do i10 = 1 , idlim ! search for next delimiter ifound = index ( input_line ( ibegin ( i30 ): ilen ), dlim ( i10 : i10 )) IF ( ifound > 0 ) then iterm ( i30 ) = min ( iterm ( i30 ), ifound + ibegin ( i30 ) - 2 ) endif enddo icol = iterm ( i30 ) + 2 ! next place to look as found end of this token inotnull = inotnull + 1 ! increment count of number of tokens not composed of delimiters else ! character is a delimiter for a null string iterm ( i30 ) = icol - 1 ! record assumed end of string. Will be less than beginning icol = icol + 1 ! advance pointer into input string endif imax = max ( imax , iterm ( i30 ) - ibegin ( i30 ) + 1 ) icount = i30 ! increment count of number of tokens found if ( icol > ilen ) then ! no text left exit INFINITE endif enddo INFINITE end select select case ( trim ( adjustl ( nlls ))) case ( 'ignore' , '' , 'ignoreend' ) ireturn = inotnull case default ireturn = icount end select allocate ( character ( len = imax ) :: array ( ireturn )) ! allocate the array to return !allocate(array(ireturn)) ! allocate the array to turn select case ( trim ( adjustl ( ordr ))) ! decide which order to store tokens case ( 'reverse' , 'right' ) ; ii = ireturn ; iiii =- 1 ! last to first case default ; ii = 1 ; iiii = 1 ! first to last end select do i20 = 1 , icount ! fill the array with the tokens that were found if ( iterm ( i20 ) < ibegin ( i20 )) then select case ( trim ( adjustl ( nlls ))) case ( 'ignore' , '' , 'ignoreend' ) case default array ( ii ) = ' ' ii = ii + iiii end select else array ( ii ) = input_line ( ibegin ( i20 ): iterm ( i20 )) ii = ii + iiii endif enddo end subroutine split","tags":"","loc":"proc/split.html"},{"title":"split_first_last – Fortran-lang/fpm","text":"public pure subroutine split_first_last(string, set, first, last) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string character(len=*), intent(in) :: set integer, intent(out), allocatable :: first (:) integer, intent(out), allocatable :: last (:) Source Code pure subroutine split_first_last ( string , set , first , last ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: set integer , allocatable , intent ( out ) :: first (:) integer , allocatable , intent ( out ) :: last (:) integer , dimension ( len ( string ) + 1 ) :: istart , iend integer :: p , n , slen slen = len ( string ) n = 0 if ( slen > 0 ) then p = 0 do while ( p < slen ) n = n + 1 istart ( n ) = min ( p + 1 , slen ) call split_pos ( string , set , p ) iend ( n ) = p - 1 end do end if first = istart (: n ) last = iend (: n ) end subroutine split_first_last","tags":"","loc":"proc/split_first_last.html"},{"title":"fnv_1a – Fortran-lang/fpm","text":"public interface fnv_1a Module Procedures private pure function fnv_1a_char(input, seed) result(hash) Hash a character(*) string of default kind Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: input integer(kind=int64), intent(in), optional :: seed Return Value integer(kind=int64) private pure function fnv_1a_string_t(input, seed) result(hash) Hash a string_t array of default kind Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: input (:) integer(kind=int64), intent(in), optional :: seed Return Value integer(kind=int64)","tags":"","loc":"interface/fnv_1a.html"},{"title":"len_trim – Fortran-lang/fpm","text":"public interface len_trim Module Procedures private elemental function string_len_trim(string) result(n) Determine total trimmed length of string_t array Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: string Return Value integer private pure function strings_len_trim(strings) result(n) Determine total trimmed length of string_t array Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: strings (:) Return Value integer","tags":"","loc":"interface/len_trim.html"},{"title":"operator(.in.) – Fortran-lang/fpm","text":"public interface operator(.in.) Module Procedures public function string_array_contains (search_string, array) Check if array of TYPE(STRING_T) matches a particular CHARACTER string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: search_string type( string_t ), intent(in) :: array (:) Return Value logical","tags":"","loc":"interface/operator(.in.).html"},{"title":"operator(==) – Fortran-lang/fpm","text":"public interface operator(==) Module Procedures private pure function string_is_same(this, that) Check that two string objects are exactly identical Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: this two strings to be compared type( string_t ), intent(in) :: that two strings to be compared Return Value logical private pure function string_arrays_same(this, that) Check that two allocatable string object arrays are exactly identical Arguments Type Intent Optional Attributes Name type( string_t ), intent(in), allocatable :: this (:) two string arrays to be compared type( string_t ), intent(in), allocatable :: that (:) two string arrays to be compared Return Value logical","tags":"","loc":"interface/operator(==).html"},{"title":"resize – Fortran-lang/fpm","text":"public interface resize Module Procedures private subroutine resize_string(list, n) increase the size of a TYPE(STRING_T) array by N elements Arguments Type Intent Optional Attributes Name type( string_t ), intent(inout), allocatable :: list (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size","tags":"","loc":"interface/resize~3.html"},{"title":"str – Fortran-lang/fpm","text":"public interface str Module Procedures private pure function str_int(i) result(s) Converts integer “i” to string Arguments Type Intent Optional Attributes Name integer, intent(in) :: i Return Value character(len=str_int_len) private pure function str_int64(i) result(s) Converts integer “i” to string Arguments Type Intent Optional Attributes Name integer(kind=int64), intent(in) :: i Return Value character(len=str_int64_len) private pure function str_logical(l) result(s) Converts logical “l” to string Arguments Type Intent Optional Attributes Name logical, intent(in) :: l Return Value character(len=str_logical_len)","tags":"","loc":"interface/str.html"},{"title":"str_ends_with – Fortran-lang/fpm","text":"public interface str_ends_with Module Procedures private pure function str_ends_with_str(s, e) result(r) test if a CHARACTER string ends with a specified suffix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e Return Value logical private pure function str_ends_with_any(s, e) result(r) test if a CHARACTER string ends with any of an array of suffixs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e (:) Return Value logical private pure function str_ends_with_any_string(s, e) result(r) Test if a CHARACTER string ends with any of an array of string suffixs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s type( string_t ), intent(in) :: e (:) Return Value logical","tags":"","loc":"interface/str_ends_with.html"},{"title":"string_t – Fortran-lang/fpm","text":"public interface string_t Module Procedures private function new_string_t(s) result(string) Helper function to generate a new string_t instance\n (Required due to the allocatable component) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s Return Value type( string_t )","tags":"","loc":"interface/string_t.html"},{"title":"OS_NAME – Fortran-lang/fpm","text":"public pure function OS_NAME(os) Return string describing the OS type flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: os Return Value character(len=:), allocatable Source Code pure function OS_NAME ( os ) integer , intent ( in ) :: os character ( len = :), allocatable :: OS_NAME select case ( os ) case ( OS_LINUX ); OS_NAME = \"Linux\" case ( OS_MACOS ); OS_NAME = \"macOS\" case ( OS_WINDOWS ); OS_NAME = \"Windows\" case ( OS_CYGWIN ); OS_NAME = \"Cygwin\" case ( OS_SOLARIS ); OS_NAME = \"Solaris\" case ( OS_FREEBSD ); OS_NAME = \"FreeBSD\" case ( OS_OPENBSD ); OS_NAME = \"OpenBSD\" case ( OS_UNKNOWN ); OS_NAME = \"Unknown\" case default ; OS_NAME = \"UNKNOWN\" end select end function OS_NAME","tags":"","loc":"proc/os_name.html"},{"title":"delete_env – Fortran-lang/fpm","text":"public function delete_env(name) result(success) Deletes an environment variable for the current environment using the C standard library\nReturns an error if the variable did not exist in the first place C strings Call setenv Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Variable name Return Value logical Source Code logical function delete_env ( name ) result ( success ) !> Variable name character ( * ), intent ( in ) :: name ! Local variables integer ( c_int ) :: cerr character ( kind = c_char , len = 1 ), allocatable :: c_name (:) interface integer ( c_int ) function c_unsetenv ( envname ) bind ( C , name = \"c_unsetenv\" ) import c_int , c_char implicit none !> Pointer to the name string character ( kind = c_char , len = 1 ), intent ( in ) :: envname ( * ) end function c_unsetenv end interface !> C strings call f2cs ( name , c_name ) !> Call setenv #ifndef FPM_BOOTSTRAP cerr = c_unsetenv ( c_name ) #endif success = cerr == 0_c_int end function delete_env","tags":"","loc":"proc/delete_env.html"},{"title":"get_command_arguments_quoted – Fortran-lang/fpm","text":"public function get_command_arguments_quoted() result(args) Arguments None Return Value character(len=:), allocatable Source Code function get_command_arguments_quoted () result ( args ) character ( len = :), allocatable :: args character ( len = :), allocatable :: arg character ( len = 1 ) :: quote integer :: ilength , istatus , i ilength = 0 args = '' quote = merge ( '\"' , \"'\" , separator () == '\\') do i=2,command_argument_count() ! look at all arguments after subcommand call get_command_argument(number=i,length=ilength,status=istatus) if(istatus /= 0) then write(stderr,' ( * ( g0 , 1 x )) ')' < ERROR >* get_command_arguments_stack * error obtaining argument ',i exit else if(allocated(arg))deallocate(arg) allocate(character(len=ilength) :: arg) call get_command_argument(number=i,value=arg,length=ilength,status=istatus) if(istatus /= 0) then write(stderr,' ( * ( g0 , 1 x )) ')' < ERROR >* get_command_arguments_stack * error obtaining argument ',i exit elseif(ilength>0)then if(index(arg//' ',' - ')/=1)then args=args//quote//arg//quote//' ' elseif(index(arg,' ')/=0)then args=args//quote//arg//quote//' ' else args=args//arg//' ' endif else args=args//repeat(quote,2)//' ' endif endif enddo end function get_command_arguments_quoted","tags":"","loc":"proc/get_command_arguments_quoted.html"},{"title":"get_env – Fortran-lang/fpm","text":"public function get_env(NAME, DEFAULT) result(VALUE) get named environment variable value. It it is blank or\n not set return the optional default value\n!print , NAME, ” is not defined in the environment. Strange…”\n!print , “This processor doesn’t support environment variables. Boooh!” Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: NAME name of environment variable to get the value of character(len=*), intent(in), optional :: DEFAULT default value to return if the requested value is undefined or blank Return Value character(len=:), allocatable the returned value Source Code function get_env ( NAME , DEFAULT ) result ( VALUE ) implicit none !> name of environment variable to get the value of character ( len =* ), intent ( in ) :: NAME !> default value to return if the requested value is undefined or blank character ( len =* ), intent ( in ), optional :: DEFAULT !> the returned value character ( len = :), allocatable :: VALUE integer :: howbig integer :: stat integer :: length ! get length required to hold value length = 0 if ( NAME /= '' ) then call get_environment_variable ( NAME , length = howbig , status = stat , trim_name = . true .) select case ( stat ) case ( 1 ) !*!print *, NAME, \" is not defined in the environment. Strange...\" VALUE = '' case ( 2 ) !*!print *, \"This processor doesn't support environment variables. Boooh!\" VALUE = '' case default ! make string to hold value of sufficient size allocate ( character ( len = max ( howbig , 1 )) :: VALUE ) ! get value call get_environment_variable ( NAME , VALUE , status = stat , trim_name = . true .) if ( stat /= 0 ) VALUE = '' end select else VALUE = '' endif if ( VALUE == '' . and . present ( DEFAULT )) VALUE = DEFAULT end function get_env","tags":"","loc":"proc/get_env.html"},{"title":"get_os_type – Fortran-lang/fpm","text":"public function get_os_type() result(r) Determine the OS type Returns one of OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, OS_CYGWIN,\nOS_SOLARIS, OS_FREEBSD, OS_OPENBSD. At first, the environment variable OS is checked, which is usually\nfound on Windows. Then, OSTYPE is read in and compared with common\nnames. If this fails too, check the existence of files that can be\nfound on specific system types only. Returns OS_UNKNOWN if the operating system cannot be determined. Arguments None Return Value integer Source Code integer function get_os_type () result ( r ) !! !! Returns one of OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, OS_CYGWIN, !! OS_SOLARIS, OS_FREEBSD, OS_OPENBSD. !! !! At first, the environment variable `OS` is checked, which is usually !! found on Windows. Then, `OSTYPE` is read in and compared with common !! names. If this fails too, check the existence of files that can be !! found on specific system types only. !! !! Returns OS_UNKNOWN if the operating system cannot be determined. character ( len = 255 ) :: val integer :: length , rc logical :: file_exists logical , save :: first_run = . true . integer , save :: ret = OS_UNKNOWN !$omp threadprivate(ret, first_run) if (. not . first_run ) then r = ret return end if first_run = . false . r = OS_UNKNOWN ! Check environment variable `OSTYPE`. call get_environment_variable ( 'OSTYPE' , val , length , rc ) if ( rc == 0 . and . length > 0 ) then ! Linux if ( index ( val , 'linux' ) > 0 ) then r = OS_LINUX ret = r return end if ! macOS if ( index ( val , 'darwin' ) > 0 ) then r = OS_MACOS ret = r return end if ! Windows, MSYS, MinGW, Git Bash if ( index ( val , 'win' ) > 0 . or . index ( val , 'msys' ) > 0 ) then r = OS_WINDOWS ret = r return end if ! Cygwin if ( index ( val , 'cygwin' ) > 0 ) then r = OS_CYGWIN ret = r return end if ! Solaris, OpenIndiana, ... if ( index ( val , 'SunOS' ) > 0 . or . index ( val , 'solaris' ) > 0 ) then r = OS_SOLARIS ret = r return end if ! FreeBSD if ( index ( val , 'FreeBSD' ) > 0 . or . index ( val , 'freebsd' ) > 0 ) then r = OS_FREEBSD ret = r return end if ! OpenBSD if ( index ( val , 'OpenBSD' ) > 0 . or . index ( val , 'openbsd' ) > 0 ) then r = OS_OPENBSD ret = r return end if end if ! Check environment variable `OS`. call get_environment_variable ( 'OS' , val , length , rc ) if ( rc == 0 . and . length > 0 . and . index ( val , 'Windows_NT' ) > 0 ) then r = OS_WINDOWS ret = r return end if ! Linux inquire ( file = '/etc/os-release' , exist = file_exists ) if ( file_exists ) then r = OS_LINUX ret = r return end if ! macOS inquire ( file = '/usr/bin/sw_vers' , exist = file_exists ) if ( file_exists ) then r = OS_MACOS ret = r return end if ! FreeBSD inquire ( file = '/bin/freebsd-version' , exist = file_exists ) if ( file_exists ) then r = OS_FREEBSD ret = r return end if end function get_os_type","tags":"","loc":"proc/get_os_type.html"},{"title":"os_is_unix – Fortran-lang/fpm","text":"public function os_is_unix(os) Compare the output of get_os_type or the optional\npassed INTEGER value to the value for OS_WINDOWS\nand return .TRUE. if they match and .FALSE. otherwise Arguments Type Intent Optional Attributes Name integer, intent(in), optional :: os Return Value logical Source Code logical function os_is_unix ( os ) integer , intent ( in ), optional :: os integer :: build_os if ( present ( os )) then build_os = os else build_os = get_os_type () end if os_is_unix = build_os /= OS_WINDOWS end function os_is_unix","tags":"","loc":"proc/os_is_unix.html"},{"title":"separator – Fortran-lang/fpm","text":"public function separator() result(sep) NAME separator(3f) - [M_io:ENVIRONMENT] try to determine pathname directory separator character\n(LICENSE:PD) SYNOPSIS function separator() result ( sep ) character ( len = 1 ) :: sep DESCRIPTION First using the name the program was invoked with , then the name returned by an INQUIRE ( 3 f ) of that name , then \".\\NAME\" and \"./NAME\" try to determine the separator character used to separate directory names from file basenames . If a slash or backslash is not found in the name , the environment variable PATH is examined first for a backslash , then a slash . Can be very system dependent . If the queries fail the default returned is \"/\" . EXAMPLE sample usage program demo_separator use M_io , only : separator implicit none write ( * , * ) ' separator = ' , separator () end program demo_separator !write( , )’ unknown system directory path separator’\nifort_bug*!sep_cache=sep Arguments None Return Value character(len=1) ifort_bug*!character(len=1),save :: sep_cache=’ ‘ Source Code function separator () result ( sep ) !> !!##NAME !! separator(3f) - [M_io:ENVIRONMENT] try to determine pathname directory separator character !! (LICENSE:PD) !! !!##SYNOPSIS !! !! function separator() result(sep) !! !! character(len=1) :: sep !! !!##DESCRIPTION !! First using the name the program was invoked with, then the name !! returned by an INQUIRE(3f) of that name, then \".\\NAME\" and \"./NAME\" !! try to determine the separator character used to separate directory !! names from file basenames. !! !! If a slash or backslash is not found in the name, the environment !! variable PATH is examined first for a backslash, then a slash. !! !! Can be very system dependent. If the queries fail the default returned !! is \"/\". !! !!##EXAMPLE !! !! sample usage !! !! program demo_separator !! use M_io, only : separator !! implicit none !! write(*,*)'separator=',separator() !! end program demo_separator ! use the pathname returned as arg0 to determine pathname separator implicit none character ( len = :), allocatable :: arg0 integer :: arg0_length integer :: istat logical :: existing character ( len = 1 ) :: sep !*ifort_bug*!character(len=1),save :: sep_cache=' ' character ( len = 4096 ) :: name character ( len = :), allocatable :: fname !*ifort_bug*! if(sep_cache/=' ')then ! use cached value. NOTE: A parallel code might theoretically use multiple OS !*ifort_bug*! sep=sep_cache !*ifort_bug*! return !*ifort_bug*! endif arg0_length = 0 name = ' ' call get_command_argument ( 0 , length = arg0_length , status = istat ) if ( allocated ( arg0 )) deallocate ( arg0 ) allocate ( character ( len = arg0_length ) :: arg0 ) call get_command_argument ( 0 , arg0 , status = istat ) ! check argument name if ( index ( arg0 , '\\')/=0)then sep=' \\ ' elseif(index(arg0,' / ')/=0)then sep=' / ' else ! try name returned by INQUIRE(3f) existing=.false. name=' ' inquire(file=arg0,iostat=istat,exist=existing,name=name) if(index(name,' \\ ')/=0)then sep=' \\ ' elseif(index(name,' / ')/=0)then sep=' / ' else ! well, try some common syntax and assume in current directory fname=' . \\ '//arg0 inquire(file=fname,iostat=istat,exist=existing) if(existing)then sep=' \\ ' else fname=' . / '//arg0 inquire(file=fname,iostat=istat,exist=existing) if(existing)then sep=' / ' else ! check environment variable PATH sep=merge(' \\ ',' / ',index(get_env(' PATH '),' \\ ')/=0) !*!write(*,*)' < WARNING > unknown system directory path separator ' endif endif endif endif !*ifort_bug*!sep_cache=sep end function separator","tags":"","loc":"proc/separator.html"},{"title":"set_env – Fortran-lang/fpm","text":"public function set_env(name, value, overwrite) Set an environment variable for the current environment using the C standard library Overwrite setting\nC strings\nCall setenv Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Variable name character(len=*), intent(in) :: value Variable value logical, intent(in), optional :: overwrite Should a former value be overwritten? default = .true. Return Value logical Source Code logical function set_env ( name , value , overwrite ) !> Variable name character ( * ), intent ( in ) :: name !> Variable value character ( * ), intent ( in ) :: value !> Should a former value be overwritten? default = .true. logical , optional , intent ( in ) :: overwrite ! Local variables logical :: can_overwrite integer ( c_int ) :: cover , cerr character ( kind = c_char , len = 1 ), allocatable :: c_value (:), c_name (:) interface integer ( c_int ) function c_setenv ( envname , envval , overwrite ) & bind ( C , name = \"c_setenv\" ) import c_int , c_char implicit none !> Pointer to the name string character ( kind = c_char , len = 1 ), intent ( in ) :: envname ( * ) !> Pointer to the value string character ( kind = c_char , len = 1 ), intent ( in ) :: envval ( * ) !> Overwrite option integer ( c_int ), intent ( in ), value :: overwrite end function c_setenv end interface !> Overwrite setting can_overwrite = . true . if ( present ( overwrite )) can_overwrite = overwrite cover = merge ( 1_c_int , 0_c_int , can_overwrite ) !> C strings call f2cs ( name , c_name ) call f2cs ( value , c_value ) !> Call setenv #ifndef FPM_BOOTSTRAP cerr = c_setenv ( c_name , c_value , cover ) #endif set_env = cerr == 0_c_int end function set_env","tags":"","loc":"proc/set_env.html"},{"title":"build_package – Fortran-lang/fpm","text":"public subroutine build_package(targets, model, verbose) Top-level routine to build package described by model Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout) :: targets (:) type( fpm_model_t ), intent(in) :: model logical, intent(in) :: verbose Source Code subroutine build_package ( targets , model , verbose ) type ( build_target_ptr ), intent ( inout ) :: targets (:) type ( fpm_model_t ), intent ( in ) :: model logical , intent ( in ) :: verbose integer :: i , j type ( build_target_ptr ), allocatable :: queue (:) integer , allocatable :: schedule_ptr (:), stat (:) logical :: build_failed , skip_current type ( string_t ), allocatable :: build_dirs (:) type ( string_t ) :: temp type ( build_progress_t ) :: progress logical :: plain_output ! Need to make output directory for include (mod) files allocate ( build_dirs ( 0 )) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( target % output_dir . in . build_dirs ) cycle temp % s = target % output_dir build_dirs = [ build_dirs , temp ] end associate end do do i = 1 , size ( build_dirs ) call mkdir ( build_dirs ( i )% s , verbose ) end do ! Perform depth-first topological sort of targets do i = 1 , size ( targets ) call sort_target ( targets ( i )% ptr ) end do ! Construct build schedule queue call schedule_targets ( queue , schedule_ptr , targets ) ! Check if queue is empty if (. not . verbose . and . size ( queue ) < 1 ) then write ( stderr , '(a)' ) 'Project is up to date' return end if ! Initialise build status flags allocate ( stat ( size ( queue ))) stat (:) = 0 build_failed = . false . ! Set output mode #ifndef FPM_BOOTSTRAP plain_output = (. not .( c_isatty () == 1 )) . or . verbose #else plain_output = . true . #endif progress = build_progress_t ( queue , plain_output ) ! Loop over parallel schedule regions do i = 1 , size ( schedule_ptr ) - 1 ! Build targets in schedule region i !$omp parallel do default(shared) private(skip_current) schedule(dynamic,1) do j = schedule_ptr ( i ),( schedule_ptr ( i + 1 ) - 1 ) ! Check if build already failed !$omp atomic read skip_current = build_failed if (. not . skip_current ) then call progress % compiling_status ( j ) call build_target ( model , queue ( j )% ptr , verbose , stat ( j )) call progress % completed_status ( j , stat ( j )) end if ! Set global flag if this target failed to build if ( stat ( j ) /= 0 ) then !$omp atomic write build_failed = . true . end if end do ! Check if this schedule region failed: exit with message if failed if ( build_failed ) then write ( * , * ) do j = 1 , size ( stat ) if ( stat ( j ) /= 0 ) Then call print_build_log ( queue ( j )% ptr ) end if end do do j = 1 , size ( stat ) if ( stat ( j ) /= 0 ) then write ( stderr , '(*(g0:,1x))' ) ' Compilation failed for object \"' , basename ( queue ( j )% ptr % output_file ), '\"' end if end do call fpm_stop ( 1 , 'stopping due to failed compilation' ) end if end do call progress % success () end subroutine build_package","tags":"","loc":"proc/build_package.html"},{"title":"schedule_targets – Fortran-lang/fpm","text":"public subroutine schedule_targets(queue, schedule_ptr, targets) Construct a build schedule from the sorted targets. The schedule is broken into regions, described by schedule_ptr ,\n where targets in each region can be compiled in parallel. Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(out), allocatable :: queue (:) integer, allocatable :: schedule_ptr (:) type( build_target_ptr ), intent(in) :: targets (:) Source Code subroutine schedule_targets ( queue , schedule_ptr , targets ) type ( build_target_ptr ), allocatable , intent ( out ) :: queue (:) integer , allocatable :: schedule_ptr (:) type ( build_target_ptr ), intent ( in ) :: targets (:) integer :: i , j integer :: n_schedule , n_sorted n_schedule = 0 ! Number of schedule regions n_sorted = 0 ! Total number of targets to build do i = 1 , size ( targets ) if ( targets ( i )% ptr % sorted ) then n_sorted = n_sorted + 1 end if n_schedule = max ( n_schedule , targets ( i )% ptr % schedule ) end do allocate ( queue ( n_sorted )) allocate ( schedule_ptr ( n_schedule + 1 )) ! Construct the target queue and schedule region pointer n_sorted = 1 schedule_ptr ( n_sorted ) = 1 do i = 1 , n_schedule do j = 1 , size ( targets ) if ( targets ( j )% ptr % sorted ) then if ( targets ( j )% ptr % schedule == i ) then queue ( n_sorted )% ptr => targets ( j )% ptr n_sorted = n_sorted + 1 end if end if end do schedule_ptr ( i + 1 ) = n_sorted end do end subroutine schedule_targets","tags":"","loc":"proc/schedule_targets.html"},{"title":"sort_target – Fortran-lang/fpm","text":"public recursive subroutine sort_target(target) Topologically sort a target for scheduling by\n recursing over its dependencies. Checks disk-cached source hashes to determine if objects are\n up-to-date. Up-to-date sources are tagged as skipped. On completion, target should either be marked as\nsorted ( target%sorted=.true. ) or skipped ( target%skip=.true. ) If target is marked as sorted, target%schedule should be an\ninteger greater than zero indicating the region for scheduling Arguments Type Intent Optional Attributes Name type( build_target_t ), intent(inout), target :: target Source Code recursive subroutine sort_target ( target ) type ( build_target_t ), intent ( inout ), target :: target integer :: i , fh , stat ! Check if target has already been processed (as a dependency) if ( target % sorted . or . target % skip ) then return end if ! Check for a circular dependency ! (If target has been touched but not processed) if ( target % touched ) then call fpm_stop ( 1 , '(!) Circular dependency found with: ' // target % output_file ) else target % touched = . true . ! Set touched flag end if ! Load cached source file digest if present if (. not . allocated ( target % digest_cached ) . and . & exists ( target % output_file ) . and . & exists ( target % output_file // '.digest' )) then allocate ( target % digest_cached ) open ( newunit = fh , file = target % output_file // '.digest' , status = 'old' ) read ( fh , * , iostat = stat ) target % digest_cached close ( fh ) if ( stat /= 0 ) then ! Cached digest is not recognized deallocate ( target % digest_cached ) end if end if if ( allocated ( target % source )) then ! Skip if target is source-based and source file is unmodified if ( allocated ( target % digest_cached )) then if ( target % digest_cached == target % source % digest ) target % skip = . true . end if elseif ( exists ( target % output_file )) then ! Skip if target is not source-based and already exists target % skip = . true . end if ! Loop over target dependencies target % schedule = 1 do i = 1 , size ( target % dependencies ) ! Sort dependency call sort_target ( target % dependencies ( i )% ptr ) if (. not . target % dependencies ( i )% ptr % skip ) then ! Can't skip target if any dependency is not skipped target % skip = . false . ! Set target schedule after all of its dependencies target % schedule = max ( target % schedule , target % dependencies ( i )% ptr % schedule + 1 ) end if end do ! Mark flag as processed: either sorted or skipped target % sorted = . not . target % skip end subroutine sort_target","tags":"","loc":"proc/sort_target.html"},{"title":"new_fortran_config – Fortran-lang/fpm","text":"public subroutine new_fortran_config(self, table, error) Construct a new build configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( fortran_config_t ), intent(out) :: self Instance of the fortran configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling Source Code subroutine new_fortran_config ( self , table , error ) !> Instance of the fortran configuration type ( fortran_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat character (:), allocatable :: source_form call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"implicit-typing\" , self % implicit_typing , . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'implicit-typing' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"implicit-external\" , self % implicit_external , . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'implicit-external' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"source-form\" , source_form , \"free\" , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'source-form' in fpm.toml, expecting logical\" ) return end if select case ( source_form ) case default call fatal_error ( error , \"Value of source-form cannot be '\" // source_form // \"'\" ) return case ( \"free\" , \"fixed\" , \"default\" ) self % source_form = source_form end select end subroutine new_fortran_config","tags":"","loc":"proc/new_fortran_config.html"},{"title":"build_model – Fortran-lang/fpm","text":"public subroutine build_model(model, settings, package, error) Constructs a valid fpm model from command line settings and the toml manifest.\nAdd this dependency’s manifest macros Add this dependency’s package-level macros Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(out) :: model class( fpm_build_settings ), intent(inout) :: settings type( package_config_t ), intent(inout) :: package type( error_t ), intent(out), allocatable :: error Source Code subroutine build_model ( model , settings , package , error ) type ( fpm_model_t ), intent ( out ) :: model class ( fpm_build_settings ), intent ( inout ) :: settings type ( package_config_t ), intent ( inout ) :: package type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j type ( package_config_t ) :: dependency character ( len = :), allocatable :: manifest , lib_dir logical :: has_cpp logical :: duplicates_found type ( string_t ) :: include_dir model % package_name = package % name allocate ( model % include_dirs ( 0 )) allocate ( model % link_libraries ( 0 )) allocate ( model % external_modules ( 0 )) call new_compiler ( model % compiler , settings % compiler , settings % c_compiler , & & settings % cxx_compiler , echo = settings % verbose , verbose = settings % verbose ) call new_archiver ( model % archiver , settings % archiver , & & echo = settings % verbose , verbose = settings % verbose ) if ( model % compiler % is_unknown ()) then write ( * , '(*(a:,1x))' ) & \"\" , \"Unknown compiler\" , model % compiler % fc , \"requested!\" , & \"Defaults for this compiler might be incorrect\" end if call new_compiler_flags ( model , settings ) model % build_prefix = join_path ( \"build\" , basename ( model % compiler % fc )) model % include_tests = settings % build_tests model % enforce_module_names = package % build % module_naming model % module_prefix = package % build % module_prefix ! Resolve meta-dependencies into the package and the model call resolve_metapackages ( model , package , settings , error ) if ( allocated ( error )) return ! Create dependencies call new_dependency_tree ( model % deps , cache = join_path ( \"build\" , \"cache.toml\" )) ! Build and resolve model dependencies call model % deps % add ( package , error ) if ( allocated ( error )) return ! Update dependencies where needed call model % deps % update ( error ) if ( allocated ( error )) return ! build/ directory should now exist if (. not . exists ( \"build/.gitignore\" )) then call filewrite ( join_path ( \"build\" , \".gitignore\" ),[ \"*\" ]) end if allocate ( model % packages ( model % deps % ndep )) has_cpp = . false . do i = 1 , model % deps % ndep associate ( dep => model % deps % dep ( i )) manifest = join_path ( dep % proj_dir , \"fpm.toml\" ) call get_package_data ( dependency , manifest , error , apply_defaults = . true .) if ( allocated ( error )) exit model % packages ( i )% name = dependency % name associate ( features => model % packages ( i )% features ) features % implicit_typing = dependency % fortran % implicit_typing features % implicit_external = dependency % fortran % implicit_external features % source_form = dependency % fortran % source_form end associate model % packages ( i )% version = package % version % s () !> Add this dependency's manifest macros call model % packages ( i )% preprocess % destroy () if ( allocated ( dependency % preprocess )) then do j = 1 , size ( dependency % preprocess ) call model % packages ( i )% preprocess % add_config ( dependency % preprocess ( j )) end do end if !> Add this dependency's package-level macros if ( allocated ( dep % preprocess )) then do j = 1 , size ( dep % preprocess ) call model % packages ( i )% preprocess % add_config ( dep % preprocess ( j )) end do end if if ( model % packages ( i )% preprocess % is_cpp ()) has_cpp = . true . if (. not . allocated ( model % packages ( i )% sources )) allocate ( model % packages ( i )% sources ( 0 )) if ( allocated ( dependency % library )) then if ( allocated ( dependency % library % source_dir )) then lib_dir = join_path ( dep % proj_dir , dependency % library % source_dir ) if ( is_dir ( lib_dir )) then call add_sources_from_dir ( model % packages ( i )% sources , lib_dir , FPM_SCOPE_LIB , & with_f_ext = model % packages ( i )% preprocess % suffixes , error = error ) if ( allocated ( error )) exit end if end if if ( allocated ( dependency % library % include_dir )) then do j = 1 , size ( dependency % library % include_dir ) include_dir % s = join_path ( dep % proj_dir , dependency % library % include_dir ( j )% s ) if ( is_dir ( include_dir % s )) then model % include_dirs = [ model % include_dirs , include_dir ] end if end do end if end if if ( allocated ( dependency % build % link )) then model % link_libraries = [ model % link_libraries , dependency % build % link ] end if if ( allocated ( dependency % build % external_modules )) then model % external_modules = [ model % external_modules , dependency % build % external_modules ] end if ! Copy naming conventions from this dependency's manifest model % packages ( i )% enforce_module_names = dependency % build % module_naming model % packages ( i )% module_prefix = dependency % build % module_prefix end associate end do if ( allocated ( error )) return ! Add optional flags if ( has_cpp ) call set_cpp_preprocessor_flags ( model % compiler % id , model % fortran_compile_flags ) ! Add sources from executable directories if ( is_dir ( 'app' ) . and . package % build % auto_executables ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'app' , FPM_SCOPE_APP , & with_executables = . true ., with_f_ext = model % packages ( 1 )% preprocess % suffixes ,& error = error ) if ( allocated ( error )) then return end if end if if ( is_dir ( 'example' ) . and . package % build % auto_examples ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'example' , FPM_SCOPE_EXAMPLE , & with_executables = . true ., & with_f_ext = model % packages ( 1 )% preprocess % suffixes , error = error ) if ( allocated ( error )) then return end if end if if ( is_dir ( 'test' ) . and . package % build % auto_tests ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'test' , FPM_SCOPE_TEST , & with_executables = . true ., & with_f_ext = model % packages ( 1 )% preprocess % suffixes , error = error ) if ( allocated ( error )) then return endif end if if ( allocated ( package % executable )) then call add_executable_sources ( model % packages ( 1 )% sources , package % executable , FPM_SCOPE_APP , & auto_discover = package % build % auto_executables , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return end if end if if ( allocated ( package % example )) then call add_executable_sources ( model % packages ( 1 )% sources , package % example , FPM_SCOPE_EXAMPLE , & auto_discover = package % build % auto_examples , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return end if end if if ( allocated ( package % test )) then call add_executable_sources ( model % packages ( 1 )% sources , package % test , FPM_SCOPE_TEST , & auto_discover = package % build % auto_tests , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return endif endif if ( settings % verbose ) then write ( * , * ) ' BUILD_NAME: ' , model % build_prefix write ( * , * ) ' COMPILER: ' , model % compiler % fc write ( * , * ) ' C COMPILER: ' , model % compiler % cc write ( * , * ) ' CXX COMPILER: ' , model % compiler % cxx write ( * , * ) ' COMPILER OPTIONS: ' , model % fortran_compile_flags write ( * , * ) ' C COMPILER OPTIONS: ' , model % c_compile_flags write ( * , * ) ' CXX COMPILER OPTIONS: ' , model % cxx_compile_flags write ( * , * ) ' LINKER OPTIONS: ' , model % link_flags write ( * , * ) ' INCLUDE DIRECTORIES: [' , string_cat ( model % include_dirs , ',' ), ']' end if ! Check for invalid module names call check_module_names ( model , error ) if ( allocated ( error )) return ! Check for duplicate modules duplicates_found = . false . call check_modules_for_duplicates ( model , duplicates_found ) if ( duplicates_found ) then call fpm_stop ( 1 , '*build_model*:Error: One or more duplicate module names found.' ) end if end subroutine build_model","tags":"","loc":"proc/build_model.html"},{"title":"check_modules_for_duplicates – Fortran-lang/fpm","text":"public subroutine check_modules_for_duplicates(model, duplicates_found) Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(in) :: model logical :: duplicates_found Source Code subroutine check_modules_for_duplicates ( model , duplicates_found ) type ( fpm_model_t ), intent ( in ) :: model integer :: maxsize integer :: i , j , k , l , m , modi type ( string_t ), allocatable :: modules (:) logical :: duplicates_found ! Initialise the size of array maxsize = 0 ! Get number of modules provided by each source file of every package do i = 1 , size ( model % packages ) do j = 1 , size ( model % packages ( i )% sources ) if ( allocated ( model % packages ( i )% sources ( j )% modules_provided )) then maxsize = maxsize + size ( model % packages ( i )% sources ( j )% modules_provided ) end if end do end do ! Allocate array to contain distinct names of modules allocate ( modules ( maxsize )) ! Initialise index to point at start of the newly allocated array modi = 1 ! Loop through modules provided by each source file of every package ! Add it to the array if it is not already there ! Otherwise print out warning about duplicates do k = 1 , size ( model % packages ) do l = 1 , size ( model % packages ( k )% sources ) if ( allocated ( model % packages ( k )% sources ( l )% modules_provided )) then do m = 1 , size ( model % packages ( k )% sources ( l )% modules_provided ) if ( model % packages ( k )% sources ( l )% modules_provided ( m )% s . in . modules (: modi - 1 )) then write ( stderr , * ) \"Warning: Module \" , model % packages ( k )% sources ( l )% modules_provided ( m )% s , & \" in \" , model % packages ( k )% sources ( l )% file_name , \" is a duplicate\" duplicates_found = . true . else modules ( modi ) = model % packages ( k )% sources ( l )% modules_provided ( m ) modi = modi + 1 end if end do end if end do end do end subroutine check_modules_for_duplicates","tags":"","loc":"proc/check_modules_for_duplicates.html"},{"title":"cmd_build – Fortran-lang/fpm","text":"public subroutine cmd_build(settings) Dump model to file Arguments Type Intent Optional Attributes Name type( fpm_build_settings ), intent(inout) :: settings Source Code subroutine cmd_build ( settings ) type ( fpm_build_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( error_t ), allocatable :: error integer :: i call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Package error: ' // error % message ) end if call build_model ( model , settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Model error: ' // error % message ) end if call targets_from_sources ( targets , model , settings % prune , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Target error: ' // error % message ) end if !> Dump model to file if ( len_trim ( settings % dump ) > 0 ) then call model % dump ( trim ( settings % dump ), error , json = name_is_json ( trim ( settings % dump ))) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_build* Model dump error: ' // error % message ) endif if ( settings % list ) then do i = 1 , size ( targets ) write ( stderr , * ) targets ( i )% ptr % output_file enddo else if ( settings % show_model ) then call show_model ( model ) else call build_package ( targets , model , verbose = settings % verbose ) endif end subroutine cmd_build","tags":"","loc":"proc/cmd_build.html"},{"title":"cmd_clean – Fortran-lang/fpm","text":"public subroutine cmd_clean(settings) Delete the build directory including or excluding dependencies. Can be used\nto clear the registry cache. Arguments Type Intent Optional Attributes Name class( fpm_clean_settings ), intent(in) :: settings Settings for the clean command. Source Code subroutine cmd_clean ( settings ) !> Settings for the clean command. class ( fpm_clean_settings ), intent ( in ) :: settings character :: user_response type ( fpm_global_settings ) :: global_settings type ( error_t ), allocatable :: error ! Clear registry cache if ( settings % registry_cache ) then call get_global_settings ( global_settings , error ) if ( allocated ( error )) return call os_delete_dir ( os_is_unix (), global_settings % registry_settings % cache_path ) end if if ( is_dir ( 'build' )) then ! Remove the entire build directory if ( settings % clean_all ) then call os_delete_dir ( os_is_unix (), 'build' ); return ! Remove the build directory but skip dependencies else if ( settings % clean_skip ) then call delete_skip ( os_is_unix ()); return end if ! Prompt to remove the build directory but skip dependencies write ( stdout , '(A)' , advance = 'no' ) \"Delete build, excluding dependencies (y/n)? \" read ( stdin , '(A1)' ) user_response if ( lower ( user_response ) == 'y' ) call delete_skip ( os_is_unix ()) else write ( stdout , '(A)' ) \"fpm: No build directory found.\" end if end subroutine cmd_clean","tags":"","loc":"proc/cmd_clean.html"},{"title":"cmd_run – Fortran-lang/fpm","text":"public subroutine cmd_run(settings, test) Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(inout) :: settings logical, intent(in) :: test Source Code subroutine cmd_run ( settings , test ) class ( fpm_run_settings ), intent ( inout ) :: settings logical , intent ( in ) :: test integer :: i , j , col_width logical :: found ( size ( settings % name )) type ( error_t ), allocatable :: error type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( string_t ) :: exe_cmd type ( string_t ), allocatable :: executables (:) type ( build_target_t ), pointer :: exe_target type ( srcfile_t ), pointer :: exe_source integer :: run_scope , firsterror integer , allocatable :: stat (:), target_ID (:) character ( len = :), allocatable :: line call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Package error: ' // error % message ) end if call build_model ( model , settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Model error: ' // error % message ) end if call targets_from_sources ( targets , model , settings % prune , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Targets error: ' // error % message ) end if if ( test ) then run_scope = FPM_SCOPE_TEST else run_scope = merge ( FPM_SCOPE_EXAMPLE , FPM_SCOPE_APP , settings % example ) end if ! Enumerate executable targets to run col_width = - 1 found (:) = . false . allocate ( executables ( size ( targets )), target_ID ( size ( targets ))) enumerate : do i = 1 , size ( targets ) exe_target => targets ( i )% ptr if ( should_be_run ( settings , run_scope , exe_target )) then exe_source => exe_target % dependencies ( 1 )% ptr % source col_width = max ( col_width , len ( basename ( exe_target % output_file )) + 2 ) ! Priority by name ID, or 0 if no name present (run first) j = settings % name_ID ( exe_source % exe_name ) target_ID ( i ) = j if ( j > 0 ) found ( j ) = . true . exe_cmd % s = exe_target % output_file executables ( i ) = exe_cmd else target_ID ( i ) = huge ( target_ID ( i )) endif end do enumerate ! sort executables by ascending name ID, resize call sort_executables ( target_ID , executables ) ! Check if any apps/tests were found if ( col_width < 0 ) then if ( test ) then call fpm_stop ( 0 , 'No tests to run' ) else call fpm_stop ( 0 , 'No executables to run' ) end if end if ! Check all names are valid ! or no name and found more than one file if ( any (. not . found ) ) then line = join ( settings % name ) if ( line /= '.' ) then ! do not report these special strings if ( any (. not . found )) then write ( stderr , '(A)' , advance = \"no\" ) '*cmd_run*:specified names ' do j = 1 , size ( settings % name ) if (. not . found ( j )) write ( stderr , '(A)' , advance = \"no\" ) '\"' // trim ( settings % name ( j )) // '\" ' end do write ( stderr , '(A)' ) 'not found.' write ( stderr , * ) else if ( settings % verbose ) then write ( stderr , '(A)' , advance = \"yes\" ) 'when more than one executable is available' write ( stderr , '(A)' , advance = \"yes\" ) ' program names must be specified.' endif endif call compact_list_all () if ( line == '.' . or . line == ' ' ) then ! do not report these special strings call fpm_stop ( 0 , '' ) else call fpm_stop ( 1 , '' ) endif end if call build_package ( targets , model , verbose = settings % verbose ) if ( settings % list ) then call compact_list () else allocate ( stat ( size ( executables ))) do i = 1 , size ( executables ) if ( exists ( executables ( i )% s )) then if ( settings % runner /= ' ' ) then if (. not . allocated ( settings % args )) then call run ( settings % runner_command () // ' ' // executables ( i )% s , & echo = settings % verbose , exitstat = stat ( i )) else call run ( settings % runner_command () // ' ' // executables ( i )% s // \" \" // settings % args , & echo = settings % verbose , exitstat = stat ( i )) endif else if (. not . allocated ( settings % args )) then call run ( executables ( i )% s , echo = settings % verbose , exitstat = stat ( i )) else call run ( executables ( i )% s // \" \" // settings % args , echo = settings % verbose , & exitstat = stat ( i )) endif endif else call fpm_stop ( 1 , '*cmd_run*:' // executables ( i )% s // ' not found' ) end if end do if ( any ( stat /= 0 )) then do i = 1 , size ( stat ) if ( stat ( i ) /= 0 ) then write ( stderr , '(*(g0:,1x))' ) ' Execution for object \"' , basename ( executables ( i )% s ),& '\" returned exit code ' , stat ( i ) end if end do firsterror = findloc ( stat /= 0 , value = . true ., dim = 1 ) call fpm_stop ( stat ( firsterror ), '*cmd_run*:stopping due to failed executions' ) end if end if contains subroutine compact_list_all () integer , parameter :: LINE_WIDTH = 80 integer :: ii , jj , nCol jj = 1 nCol = LINE_WIDTH / col_width write ( stderr , * ) 'Available names:' do ii = 1 , size ( targets ) exe_target => targets ( ii )% ptr if ( exe_target % target_type == FPM_TARGET_EXECUTABLE . and . & allocated ( exe_target % dependencies )) then exe_source => exe_target % dependencies ( 1 )% ptr % source if ( exe_source % unit_scope == run_scope ) then write ( stderr , '(A)' , advance = ( merge ( \"yes\" , \"no \" , modulo ( jj , nCol ) == 0 ))) & & [ character ( len = col_width ) :: basename ( exe_target % output_file , suffix = . false .)] jj = jj + 1 end if end if end do write ( stderr , * ) end subroutine compact_list_all subroutine compact_list () integer , parameter :: LINE_WIDTH = 80 integer :: ii , jj , nCol jj = 1 nCol = LINE_WIDTH / col_width write ( stderr , * ) 'Matched names:' do ii = 1 , size ( executables ) write ( stderr , '(A)' , advance = ( merge ( \"yes\" , \"no \" , modulo ( jj , nCol ) == 0 ))) & & [ character ( len = col_width ) :: basename ( executables ( ii )% s , suffix = . false .)] jj = jj + 1 end do write ( stderr , * ) end subroutine compact_list end subroutine cmd_run","tags":"","loc":"proc/cmd_run.html"},{"title":"basename – Fortran-lang/fpm","text":"public function basename(path, suffix) result(base) Extract filename from path with/without suffix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path logical, intent(in), optional :: suffix Return Value character(len=:), allocatable Source Code function basename ( path , suffix ) result ( base ) character ( * ), intent ( In ) :: path logical , intent ( in ), optional :: suffix character (:), allocatable :: base character (:), allocatable :: file_parts (:) logical :: with_suffix if (. not . present ( suffix )) then with_suffix = . true . else with_suffix = suffix end if call split ( path , file_parts , delimiters = '\\/' ) if ( size ( file_parts ) > 0 ) then base = trim ( file_parts ( size ( file_parts ))) else base = '' endif if (. not . with_suffix ) then call split ( base , file_parts , delimiters = '.' ) if ( size ( file_parts ) >= 2 ) then base = trim ( file_parts ( size ( file_parts ) - 1 )) endif endif end function basename","tags":"","loc":"proc/basename.html"},{"title":"canon_path – Fortran-lang/fpm","text":"public function canon_path(path) Canonicalize path for comparison\n* Handles path string redundancies\n* Does not test existence of path To be replaced by realpath/_fullname in stdlib_os FIXME: Lot’s of ugly hacks following here Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function canon_path ( path ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: canon_path character ( len = :), allocatable :: nixpath integer :: istart , iend , nn , last logical :: is_path , absolute nixpath = unix_path ( path ) istart = 0 nn = 0 iend = 0 absolute = nixpath ( 1 : 1 ) == \"/\" if ( absolute ) then canon_path = \"/\" else canon_path = \"\" end if do while ( iend < len ( nixpath )) call next ( nixpath , istart , iend , is_path ) if ( is_path ) then select case ( nixpath ( istart : iend )) case ( \".\" , \"\" ) ! always drop empty paths case ( \"..\" ) if ( nn > 0 ) then last = scan ( canon_path (: len ( canon_path ) - 1 ), \"/\" , back = . true .) canon_path = canon_path (: last ) nn = nn - 1 else if (. not . absolute ) then canon_path = canon_path // nixpath ( istart : iend ) // \"/\" end if end if case default nn = nn + 1 canon_path = canon_path // nixpath ( istart : iend ) // \"/\" end select end if end do if ( len ( canon_path ) == 0 ) canon_path = \".\" if ( len ( canon_path ) > 1 . and . canon_path ( len ( canon_path ):) == \"/\" ) then canon_path = canon_path (: len ( canon_path ) - 1 ) end if contains subroutine next ( string , istart , iend , is_path ) character ( len =* ), intent ( in ) :: string integer , intent ( inout ) :: istart integer , intent ( inout ) :: iend logical , intent ( inout ) :: is_path integer :: ii , nn character :: tok nn = len ( string ) if ( iend >= nn ) then istart = nn iend = nn return end if ii = min ( iend + 1 , nn ) tok = string ( ii : ii ) is_path = tok /= '/' if (. not . is_path ) then is_path = . false . istart = ii iend = ii return end if istart = ii do ii = min ( iend + 1 , nn ), nn tok = string ( ii : ii ) select case ( tok ) case ( '/' ) exit case default iend = ii cycle end select end do end subroutine next end function canon_path","tags":"","loc":"proc/canon_path.html"},{"title":"dirname – Fortran-lang/fpm","text":"public function dirname(path) result(dir) Extract dirname from path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function dirname ( path ) result ( dir ) character ( * ), intent ( in ) :: path character (:), allocatable :: dir dir = path ( 1 : scan ( path , ' / \\' , back = . true .)) end function dirname","tags":"","loc":"proc/dirname.html"},{"title":"exists – Fortran-lang/fpm","text":"public function exists(filename) result(r) test if pathname already exists Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value logical","tags":"","loc":"proc/exists.html"},{"title":"get_dos_path – Fortran-lang/fpm","text":"public function get_dos_path(path, error) Ensure a windows path is converted to an 8.3 DOS path if it contains spaces\nNo need to convert if there are no spaces Read screen output Ensure there are no trailing slashes Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path type( error_t ), intent(out), allocatable :: error Return Value character(len=:), allocatable Source Code function get_dos_path ( path , error ) character ( len =* ), intent ( in ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: get_dos_path character (:), allocatable :: redirect , screen_output , line integer :: stat , cmdstat , iunit , last ! Non-Windows OS if ( get_os_type () /= OS_WINDOWS ) then get_dos_path = path return end if ! Trim path first get_dos_path = trim ( path ) !> No need to convert if there are no spaces has_spaces : if ( scan ( get_dos_path , ' ' ) > 0 ) then redirect = get_temp_filename () call execute_command_line ( 'cmd /c for %A in (\"' // path // '\") do @echo %~sA >' // redirect // ' 2>&1' ,& exitstat = stat , cmdstat = cmdstat ) !> Read screen output command_OK : if ( cmdstat == 0 . and . stat == 0 ) then allocate ( character ( len = 0 ) :: screen_output ) open ( newunit = iunit , file = redirect , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit screen_output = screen_output // line // ' ' end do ! Close and delete file close ( iunit , status = 'delete' ) else call fatal_error ( error , 'cannot read temporary file from successful DOS path evaluation' ) return endif else command_OK call fatal_error ( error , 'unsuccessful Windows->DOS path command' ) return end if command_OK get_dos_path = trim ( adjustl ( screen_output )) endif has_spaces !> Ensure there are no trailing slashes last = len_trim ( get_dos_path ) if ( last > 1 . and . get_dos_path ( last : last ) == '/' . or . get_dos_path ( last : last ) == '\\' ) get_dos_path = get_dos_path ( 1 : last - 1 ) end function get_dos_path","tags":"","loc":"proc/get_dos_path.html"},{"title":"get_local_prefix – Fortran-lang/fpm","text":"public function get_local_prefix(os) result(prefix) Determine the path prefix to the local folder. Used for installation, registry etc. Arguments Type Intent Optional Attributes Name integer, intent(in), optional :: os Platform identifier Return Value character(len=:), allocatable Installation prefix Source Code function get_local_prefix ( os ) result ( prefix ) !> Installation prefix character ( len = :), allocatable :: prefix !> Platform identifier integer , intent ( in ), optional :: os !> Default installation prefix on Unix platforms character ( len =* ), parameter :: default_prefix_unix = \"/usr/local\" !> Default installation prefix on Windows platforms character ( len =* ), parameter :: default_prefix_win = \"C:\\\" character(len=:), allocatable :: home if (os_is_unix(os)) then home=get_env('HOME','') if (home /= '' ) then prefix = join_path(home, \" . local \") else prefix = default_prefix_unix end if else home=get_env('APPDATA','') if (home /= '' ) then prefix = join_path(home, \" local \" ) else prefix = default_prefix_win end if end if end function get_local_prefix","tags":"","loc":"proc/get_local_prefix.html"},{"title":"get_temp_filename – Fortran-lang/fpm","text":"public function get_temp_filename() result(tempfile) Uses iso_c_binding Get a unused temporary filename\n Calls posix ‘tempnam’ - not recommended, but\n we have no security concerns for this application\n and use here is temporary.\nWorks with MinGW Arguments None Return Value character(len=:), allocatable Source Code function get_temp_filename () result ( tempfile ) ! use iso_c_binding , only : c_ptr , C_NULL_PTR , c_f_pointer integer , parameter :: MAX_FILENAME_LENGTH = 32768 character (:), allocatable :: tempfile type ( c_ptr ) :: c_tempfile_ptr character ( len = 1 ), pointer :: c_tempfile (:) interface function c_tempnam ( dir , pfx ) result ( tmp ) bind ( c , name = \"tempnam\" ) import type ( c_ptr ), intent ( in ), value :: dir type ( c_ptr ), intent ( in ), value :: pfx type ( c_ptr ) :: tmp end function c_tempnam subroutine c_free ( ptr ) BIND ( C , name = \"free\" ) import type ( c_ptr ), value :: ptr end subroutine c_free end interface c_tempfile_ptr = c_tempnam ( C_NULL_PTR , C_NULL_PTR ) call c_f_pointer ( c_tempfile_ptr , c_tempfile ,[ MAX_FILENAME_LENGTH ]) tempfile = f_string ( c_tempfile ) call c_free ( c_tempfile_ptr ) end function get_temp_filename","tags":"","loc":"proc/get_temp_filename.html"},{"title":"is_absolute_path – Fortran-lang/fpm","text":"public function is_absolute_path(path, is_unix) Returns .true. if provided path is absolute. ~ not treated as absolute. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path logical, intent(in), optional :: is_unix Return Value logical Source Code logical function is_absolute_path ( path , is_unix ) character ( len =* ), intent ( in ) :: path logical , optional , intent ( in ) :: is_unix character ( len =* ), parameter :: letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' logical :: is_unix_os if ( present ( is_unix )) then is_unix_os = is_unix else is_unix_os = os_is_unix () end if if ( is_unix_os ) then is_absolute_path = path ( 1 : 1 ) == '/' else if ( len ( path ) < 2 ) then is_absolute_path = . false . return end if is_absolute_path = index ( letters , path ( 1 : 1 )) /= 0 . and . path ( 2 : 2 ) == ':' end if end function is_absolute_path","tags":"","loc":"proc/is_absolute_path.html"},{"title":"is_dir – Fortran-lang/fpm","text":"public function is_dir(dir) test if a name matches an existing directory path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir Return Value logical Source Code logical function is_dir ( dir ) character ( * ), intent ( in ) :: dir integer :: stat select case ( get_os_type ()) case ( OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD ) call run ( \"test -d \" // dir , & & exitstat = stat , echo = . false ., verbose = . false .) case ( OS_WINDOWS ) call run ( 'cmd /c \"if not exist ' // windows_path ( dir ) // '\\ exit /B 1\"' , & & exitstat = stat , echo = . false ., verbose = . false .) end select is_dir = ( stat == 0 ) end function is_dir","tags":"","loc":"proc/is_dir.html"},{"title":"is_hidden_file – Fortran-lang/fpm","text":"public function is_hidden_file(file_basename) result(r) test if a file is hidden Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file_basename Return Value logical Source Code logical function is_hidden_file ( file_basename ) result ( r ) character ( * ), intent ( in ) :: file_basename if ( len ( file_basename ) <= 2 ) then r = . false . else r = str_begins_with_str ( file_basename , '.' ) end if end function is_hidden_file","tags":"","loc":"proc/is_hidden_file.html"},{"title":"join_path – Fortran-lang/fpm","text":"public function join_path(a1, a2, a3, a4, a5) result(path) Construct path by joining strings with os file separator Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: a1 character(len=*), intent(in) :: a2 character(len=*), intent(in), optional :: a3 character(len=*), intent(in), optional :: a4 character(len=*), intent(in), optional :: a5 Return Value character(len=:), allocatable Source Code function join_path ( a1 , a2 , a3 , a4 , a5 ) result ( path ) character ( len =* ), intent ( in ) :: a1 , a2 character ( len =* ), intent ( in ), optional :: a3 , a4 , a5 character ( len = :), allocatable :: path character ( len = 1 ) :: filesep logical , save :: has_cache = . false . character ( len = 1 ), save :: cache = '/' !$omp threadprivate(has_cache, cache) if ( has_cache ) then filesep = cache else select case ( get_os_type ()) case default filesep = '/' case ( OS_WINDOWS ) filesep = '\\' end select cache = filesep has_cache = . true . end if if ( a1 == \"\" ) then path = a2 else path = a1 // filesep // a2 end if if ( present ( a3 )) then path = path // filesep // a3 else return end if if ( present ( a4 )) then path = path // filesep // a4 else return end if if ( present ( a5 )) then path = path // filesep // a5 else return end if end function join_path","tags":"","loc":"proc/join_path.html"},{"title":"number_of_rows – Fortran-lang/fpm","text":"public function number_of_rows(s) result(nrows) Determine number or rows in a file given a LUN Arguments Type Intent Optional Attributes Name integer, intent(in) :: s Return Value integer Source Code integer function number_of_rows ( s ) result ( nrows ) integer , intent ( in ) :: s integer :: ios rewind ( s ) nrows = 0 do read ( s , * , iostat = ios ) if ( ios /= 0 ) exit nrows = nrows + 1 end do rewind ( s ) end function number_of_rows","tags":"","loc":"proc/number_of_rows.html"},{"title":"parent_dir – Fortran-lang/fpm","text":"public function parent_dir(path) result(dir) Extract dirname from path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function parent_dir ( path ) result ( dir ) character ( * ), intent ( in ) :: path character (:), allocatable :: dir dir = path ( 1 : scan ( path , ' / \\' , back = . true .) - 1 ) end function parent_dir","tags":"","loc":"proc/parent_dir.html"},{"title":"read_lines – Fortran-lang/fpm","text":"public function read_lines(filename) result(lines) read lines into an array of TYPE(STRING_T) variables Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value type( string_t ), allocatable, (:) Source Code function read_lines ( filename ) result ( lines ) character ( len =* ), intent ( in ) :: filename type ( string_t ), allocatable :: lines (:) integer :: i character ( len = :), allocatable :: content integer , allocatable :: first (:), last (:) content = read_text_file ( filename ) if ( len ( content ) == 0 ) then allocate ( lines ( 0 )) return end if call split_first_last ( content , eol , first , last ) ! TODO: \\r (< macOS X), \\n (>=macOS X/Linux/Unix), \\r\\n (Windows) ! allocate lines from file content string allocate ( lines ( size ( first ))) do i = 1 , size ( first ) allocate ( lines ( i )% s , source = content ( first ( i ): last ( i ))) end do end function read_lines","tags":"","loc":"proc/read_lines.html"},{"title":"read_lines_expanded – Fortran-lang/fpm","text":"public function read_lines_expanded(filename) result(lines) read lines into an array of TYPE(STRING_T) variables expanding tabs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value type( string_t ), allocatable, (:) Source Code function read_lines_expanded ( filename ) result ( lines ) character ( len =* ), intent ( in ) :: filename type ( string_t ), allocatable :: lines (:) integer :: i character ( len = :), allocatable :: content integer , allocatable :: first (:), last (:) content = read_text_file ( filename ) if ( len ( content ) == 0 ) then allocate ( lines ( 0 )) return end if call split_first_last ( content , eol , first , last ) ! TODO: \\r (< macOS X), \\n (>=macOS X/Linux/Unix), \\r\\n (Windows) ! allocate lines from file content string allocate ( lines ( size ( first ))) do i = 1 , size ( first ) allocate ( lines ( i )% s , source = dilate ( content ( first ( i ): last ( i )))) end do end function read_lines_expanded","tags":"","loc":"proc/read_lines_expanded.html"},{"title":"unix_path – Fortran-lang/fpm","text":"public function unix_path(path) result(nixpath) Replace file system separators for unix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function unix_path ( path ) result ( nixpath ) character ( * ), intent ( in ) :: path character (:), allocatable :: nixpath integer :: idx nixpath = path idx = index ( nixpath , '\\') do while(idx > 0) nixpath(idx:idx) = ' / ' idx = index(nixpath,' \\' ) end do end function unix_path","tags":"","loc":"proc/unix_path.html"},{"title":"which – Fortran-lang/fpm","text":"public function which(command) result(pathname) Name which ( 3 f ) - [ M_io : ENVIRONMENT ] given a command name find the pathname by searching the directories in the environment variable $ PATH ( LICENSE : PD ) Syntax function which(command) result(pathname) character(len=*),intent(in) :: command\ncharacter(len=:),allocatable :: pathname Description Given a command name find the first file with that name in the directories specified by the environment variable $ PATH . options COMMAND the command to search for Returns PATHNAME the first pathname found in the current user path . Returns blank if the command is not found . Example Sample program: Checking the error message and counting lines: program demo_which use M_io , only : which implicit none write ( * , * ) ' ls is ' , which ( ' ls ' ) write ( * , * ) ' dir is ' , which ( ' dir ' ) write ( * , * ) ' install is ' , which ( ' install ' ) end program demo_which Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: command Return Value character(len=:), allocatable Source Code function which ( command ) result ( pathname ) character ( len =* ), intent ( in ) :: command character ( len = :), allocatable :: pathname , checkon , paths (:), exts (:) integer :: i , j pathname = '' call split ( get_env ( 'PATH' ), paths , delimiters = merge ( ';' , ':' , separator () == '\\')) SEARCH: do i=1,size(paths) checkon=trim(join_path(trim(paths(i)),command)) select case(separator()) case(' / ') if(exists(checkon))then pathname=checkon exit SEARCH endif case(' \\ ') if(exists(checkon))then pathname=checkon exit SEARCH endif if(exists(checkon//' . bat '))then pathname=checkon//' . bat ' exit SEARCH endif if(exists(checkon//' . exe '))then pathname=checkon//' . exe ' exit SEARCH endif call split(get_env(' PATHEXT '),exts,delimiters=' ; ') do j=1,size(exts) if(exists(checkon//' . '//trim(exts(j))))then pathname=checkon//' . ' // trim ( exts ( j )) exit SEARCH endif enddo end select enddo SEARCH end function which","tags":"","loc":"proc/which.html"},{"title":"windows_path – Fortran-lang/fpm","text":"public function windows_path(path) result(winpath) Replace file system separators for windows Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Source Code function windows_path ( path ) result ( winpath ) character ( * ), intent ( in ) :: path character (:), allocatable :: winpath integer :: idx winpath = path idx = index ( winpath , '/' ) do while ( idx > 0 ) winpath ( idx : idx ) = '\\' idx = index(winpath,' / ' ) end do end function windows_path","tags":"","loc":"proc/windows_path.html"},{"title":"delete_file – Fortran-lang/fpm","text":"public subroutine delete_file(file) delete a file by filename Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file Source Code subroutine delete_file ( file ) character ( len =* ), intent ( in ) :: file logical :: exist integer :: unit inquire ( file = file , exist = exist ) if ( exist ) then open ( file = file , newunit = unit ) close ( unit , status = \"delete\" ) end if end subroutine delete_file","tags":"","loc":"proc/delete_file.html"},{"title":"execute_and_read_output – Fortran-lang/fpm","text":"public subroutine execute_and_read_output(cmd, output, error, verbose) Execute command line and return output as a string. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: cmd Command to execute. character(len=:), intent(out), allocatable :: output Command line output. type( error_t ), intent(out), allocatable :: error Error to handle. logical, intent(in), optional :: verbose Print additional information if true.","tags":"","loc":"proc/execute_and_read_output.html"},{"title":"fileclose – Fortran-lang/fpm","text":"public subroutine fileclose(lun, ier) simple close of a LUN. On error show message and stop (by default) Arguments Type Intent Optional Attributes Name integer, intent(in) :: lun integer, intent(out), optional :: ier Source Code subroutine fileclose ( lun , ier ) integer , intent ( in ) :: lun integer , intent ( out ), optional :: ier character ( len = 256 ) :: message integer :: ios if ( lun /=- 1 ) then close ( unit = lun , iostat = ios , iomsg = message ) if ( ios /= 0 ) then if ( present ( ier )) then ier = ios else call fpm_stop ( 4 , '*fileclose*:' // trim ( message )) endif endif endif end subroutine fileclose","tags":"","loc":"proc/fileclose.html"},{"title":"fileopen – Fortran-lang/fpm","text":"public subroutine fileopen(filename, lun, ier) procedure to open filename as a sequential “text” file Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename integer, intent(out) :: lun integer, intent(out), optional :: ier Source Code subroutine fileopen ( filename , lun , ier ) character ( len =* ), intent ( in ) :: filename integer , intent ( out ) :: lun integer , intent ( out ), optional :: ier integer :: ios character ( len = 256 ) :: message message = ' ' ios = 0 if ( filename /= ' ' ) then open ( file = filename , & & newunit = lun , & & form = 'formatted' , & ! FORM = FORMATTED | UNFORMATTED & access = 'sequential' , & ! ACCESS = SEQUENTIAL| DIRECT | STREAM & action = 'write' , & ! ACTION = READ|WRITE| READWRITE & position = 'rewind' , & ! POSITION= ASIS | REWIND | APPEND & status = 'new' , & ! STATUS = NEW| REPLACE| OLD| SCRATCH| UNKNOWN & iostat = ios , & & iomsg = message ) else lun = stdout ios = 0 endif if ( ios /= 0 ) then lun =- 1 if ( present ( ier )) then ier = ios else call fpm_stop ( 3 , '*fileopen*:' // filename // ':' // trim ( message )) endif endif end subroutine fileopen","tags":"","loc":"proc/fileopen.html"},{"title":"filewrite – Fortran-lang/fpm","text":"public subroutine filewrite(filename, filedata) procedure to write filedata to file filename Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename character(len=*), intent(in) :: filedata (:) Source Code subroutine filewrite ( filename , filedata ) character ( len =* ), intent ( in ) :: filename character ( len =* ), intent ( in ) :: filedata (:) integer :: lun , i , ios character ( len = 256 ) :: message call fileopen ( filename , lun ) if ( lun /=- 1 ) then ! program currently stops on error on open, but might ! want it to continue so -1 (unallowed LUN) indicates error ! write file do i = 1 , size ( filedata ) write ( lun , '(a)' , iostat = ios , iomsg = message ) trim ( filedata ( i )) if ( ios /= 0 ) then call fpm_stop ( 5 , '*filewrite*:' // filename // ':' // trim ( message )) endif enddo endif ! close file call fileclose ( lun ) end subroutine filewrite","tags":"","loc":"proc/filewrite.html"},{"title":"get_home – Fortran-lang/fpm","text":"public subroutine get_home(home, error) Get the HOME directory on Unix and the %USERPROFILE% directory on Windows. Arguments Type Intent Optional Attributes Name character(len=:), intent(out), allocatable :: home type( error_t ), intent(out), allocatable :: error Source Code subroutine get_home ( home , error ) character ( len = :), allocatable , intent ( out ) :: home type ( error_t ), allocatable , intent ( out ) :: error if ( os_is_unix ()) then home = get_env ( 'HOME' , '' ) if ( home == '' ) then call fatal_error ( error , \"Couldn't retrieve 'HOME' variable\" ) return end if else home = get_env ( 'USERPROFILE' , '' ) if ( home == '' ) then call fatal_error ( error , \"Couldn't retrieve '%USERPROFILE%' variable\" ) return end if end if end subroutine get_home","tags":"","loc":"proc/get_home.html"},{"title":"getline – Fortran-lang/fpm","text":"public subroutine getline(unit, line, iostat, iomsg) NAME getline(3f) - [M_io:READ] read a line of arbintrary length from specified\n LUN into allocatable string (up to system line length limit)\n(LICENSE:PD) SYNTAX subroutine getline(unit,line,iostat,iomsg) integer,intent(in) :: unit\ncharacter(len=:),allocatable,intent(out) :: line\ninteger,intent(out) :: iostat\ncharacter(len=:), allocatable, optional :: iomsg DESCRIPTION Read a line of any length up to programming environment maximum line length . Requires Fortran 2003 +. It is primarily expected to be used when reading input which will then be parsed or echoed . The input file must have a PAD attribute of YES for the function to work properly , which is typically true . The simple use of a loop that repeatedly re - allocates a character variable in addition to reading the input file one buffer at a time could ( depending on the programming environment used ) be inefficient , as it could reallocate and allocate memory used for the output string with each buffer read . OPTIONS LINE The line read when IOSTAT returns as zero . LUN LUN ( Fortran logical I / O unit ) number of file open and ready to read . IOSTAT status returned by READ ( IOSTAT = IOS ) . If not zero , an error occurred or an end - of - file or end - of - record was encountered . IOMSG error message returned by system when IOSTAT is not zero . EXAMPLE Sample program: program demo_getline use , intrinsic :: iso_fortran_env , only : stdin => input_unit use , intrinsic :: iso_fortran_env , only : iostat_end use FPM_filesystem , only : getline implicit none integer :: iostat character ( len =:), allocatable :: line , iomsg open ( unit = stdin , pad = ' yes ' ) INFINITE : do call getline ( stdin , line , iostat , iomsg ) if ( iostat /= 0 ) exit INFINITE write ( * , ' ( a ) ')' [ ' //line//']' enddo INFINITE if ( iostat /= iostat_end ) then write ( * , * ) ' error reading input : ' , iomsg endif end program demo_getline Arguments Type Intent Optional Attributes Name integer, intent(in) :: unit Formatted IO unit character(len=:), intent(out), allocatable :: line Line to read integer, intent(out) :: iostat Status of operation character(len=:), optional, allocatable :: iomsg Error message Source Code subroutine getline ( unit , line , iostat , iomsg ) !> Formatted IO unit integer , intent ( in ) :: unit !> Line to read character ( len = :), allocatable , intent ( out ) :: line !> Status of operation integer , intent ( out ) :: iostat !> Error message character ( len = :), allocatable , optional :: iomsg integer , parameter :: BUFFER_SIZE = 1024 character ( len = BUFFER_SIZE ) :: buffer character ( len = 256 ) :: msg integer :: size integer :: stat allocate ( character ( len = 0 ) :: line ) do read ( unit , '(a)' , advance = 'no' , iostat = stat , iomsg = msg , size = size ) & & buffer if ( stat > 0 ) exit line = line // buffer (: size ) if ( stat < 0 ) then if ( is_iostat_eor ( stat )) then stat = 0 end if exit end if end do if ( stat /= 0 ) then if ( present ( iomsg )) iomsg = trim ( msg ) end if iostat = stat end subroutine getline","tags":"","loc":"proc/getline.html"},{"title":"list_files – Fortran-lang/fpm","text":"public recursive subroutine list_files(dir, files, recurse) Get file & directory names in directory dir using iso_c_binding. File/directory names return are relative to cwd, ie. preprended with dir Includes files starting with . except current directory and parent directory Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir type( string_t ), intent(out), allocatable :: files (:) logical, intent(in), optional :: recurse Source Code recursive subroutine list_files ( dir , files , recurse ) character ( len =* ), intent ( in ) :: dir type ( string_t ), allocatable , intent ( out ) :: files (:) logical , intent ( in ), optional :: recurse integer :: i type ( string_t ), allocatable :: dir_files (:) type ( string_t ), allocatable :: sub_dir_files (:) type ( c_ptr ) :: dir_handle type ( c_ptr ) :: dir_entry_c character ( len = :, kind = c_char ), allocatable :: fortran_name character ( len = :), allocatable :: string_fortran integer , parameter :: N_MAX = 256 type ( string_t ) :: files_tmp ( N_MAX ) integer ( kind = c_int ) :: r if ( c_is_dir ( dir ( 1 : len_trim ( dir )) // c_null_char ) == 0 ) then allocate ( files ( 0 )) return end if dir_handle = c_opendir ( dir ( 1 : len_trim ( dir )) // c_null_char ) if (. not . c_associated ( dir_handle )) then print * , 'c_opendir() failed' error stop end if i = 0 allocate ( files ( 0 )) do dir_entry_c = c_readdir ( dir_handle ) if (. not . c_associated ( dir_entry_c )) then exit else string_fortran = f_string ( c_get_d_name ( dir_entry_c )) if (( string_fortran == '.' . or . string_fortran == '..' )) then cycle end if i = i + 1 if ( i > N_MAX ) then files = [ files , files_tmp ] i = 1 end if files_tmp ( i )% s = join_path ( dir , string_fortran ) end if end do r = c_closedir ( dir_handle ) if ( r /= 0 ) then print * , 'c_closedir() failed' error stop end if if ( i > 0 ) then files = [ files , files_tmp ( 1 : i )] end if if ( present ( recurse )) then if ( recurse ) then allocate ( sub_dir_files ( 0 )) do i = 1 , size ( files ) if ( c_is_dir ( files ( i )% s // c_null_char ) /= 0 ) then call list_files ( files ( i )% s , dir_files , recurse = . true .) sub_dir_files = [ sub_dir_files , dir_files ] end if end do files = [ files , sub_dir_files ] end if end if end subroutine list_files","tags":"","loc":"proc/list_files.html"},{"title":"mkdir – Fortran-lang/fpm","text":"public subroutine mkdir(dir, echo) Create a directory. Create subdirectories as needed Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir logical, intent(in), optional :: echo Source Code subroutine mkdir ( dir , echo ) character ( len =* ), intent ( in ) :: dir logical , intent ( in ), optional :: echo integer :: stat if ( is_dir ( dir )) return select case ( get_os_type ()) case ( OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD ) call run ( 'mkdir -p ' // dir , exitstat = stat , echo = echo , verbose = . false .) case ( OS_WINDOWS ) call run ( \"mkdir \" // windows_path ( dir ), & & echo = echo , exitstat = stat , verbose = . false .) end select if ( stat /= 0 ) then call fpm_stop ( 1 , '*mkdir*:directory creation failed' ) end if end subroutine mkdir","tags":"","loc":"proc/mkdir.html"},{"title":"os_delete_dir – Fortran-lang/fpm","text":"public subroutine os_delete_dir(is_unix, dir, echo) Delete directory using system OS remove directory commands Arguments Type Intent Optional Attributes Name logical, intent(in) :: is_unix character(len=*), intent(in) :: dir logical, intent(in), optional :: echo Source Code subroutine os_delete_dir ( is_unix , dir , echo ) logical , intent ( in ) :: is_unix character ( len =* ), intent ( in ) :: dir logical , intent ( in ), optional :: echo if ( is_unix ) then call run ( 'rm -rf ' // dir , echo = echo , verbose = . false .) else call run ( 'rmdir /s/q ' // dir , echo = echo , verbose = . false .) end if end subroutine os_delete_dir","tags":"","loc":"proc/os_delete_dir.html"},{"title":"run – Fortran-lang/fpm","text":"public subroutine run(cmd, echo, exitstat, verbose, redirect) Name run(3f) - execute specified system command and selectively echo\ncommand and output to a file and/or stdout.\n(LICENSE:MIT) Syntax subroutine run(cmd,echo,exitstat,verbose,redirect)\n\n character(len=*), intent(in) :: cmd\n logical,intent(in),optional :: echo\n integer, intent(out),optional :: exitstat\n logical, intent(in), optional :: verbose\n character(*), intent(in), optional :: redirect Description Execute the specified system command. Optionally echo the command before execution return the system exit status of the command. redirect the output of the command to a file. echo command output to stdout Calling run(3f) is preferred to direct calls to\n execute_command_line(3f) in the fpm(1) source to provide a standard\n interface where output modes can be specified. Options CMD System command to execute ECHO Whether to echo the command being executed or not Defaults to . TRUE . . VERBOSE Whether to redirect the command output to a null device or not Defaults to . TRUE . . REDIRECT Filename to redirect stdout and stderr of the command into . If generated it is closed before run ( 3 f ) returns . EXITSTAT The system exit status of the command when supported by the system . If not present and a non - zero status is generated program termination occurs . Example Sample program: Checking the error message and counting lines: program demo_run use fpm_filesystem , only : run implicit none logical , parameter :: T =. true ., F =. false . integer :: exitstat character ( len =:), allocatable :: cmd cmd = ' ls - ltrasd * . md ' call run ( cmd ) call run ( cmd , exitstat = exitstat ) call run ( cmd , echo = F ) call run ( cmd , verbose = F ) end program demo_run Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: cmd logical, intent(in), optional :: echo integer, intent(out), optional :: exitstat logical, intent(in), optional :: verbose character(len=*), intent(in), optional :: redirect Source Code subroutine run ( cmd , echo , exitstat , verbose , redirect ) character ( len =* ), intent ( in ) :: cmd logical , intent ( in ), optional :: echo integer , intent ( out ), optional :: exitstat logical , intent ( in ), optional :: verbose character ( * ), intent ( in ), optional :: redirect integer :: cmdstat character ( len = 256 ) :: cmdmsg , iomsg logical :: echo_local , verbose_local character (:), allocatable :: redirect_str character (:), allocatable :: line integer :: stat , fh , iostat if ( present ( echo )) then echo_local = echo else echo_local = . true . end if if ( present ( verbose )) then verbose_local = verbose else verbose_local = . true . end if if ( present ( redirect )) then if ( redirect /= '' ) then redirect_str = \">\" // redirect // \" 2>&1\" else redirect_str = \"\" endif else if ( verbose_local ) then ! No redirection but verbose output redirect_str = \"\" else ! No redirection and non-verbose output if ( os_is_unix ()) then redirect_str = \" >/dev/null 2>&1\" else redirect_str = \" >NUL 2>&1\" end if end if end if if ( echo_local ) print * , '+ ' , cmd !//redirect_str call execute_command_line ( cmd // redirect_str , exitstat = stat , cmdstat = cmdstat , cmdmsg = cmdmsg ) if ( cmdstat /= 0 ) then write ( * , '(a)' ) ':failed command ' // cmd // redirect_str call fpm_stop ( 1 , '*run*:' // trim ( cmdmsg )) endif if ( verbose_local . and . present ( redirect )) then open ( newunit = fh , file = redirect , status = 'old' , iostat = iostat , iomsg = iomsg ) if ( iostat == 0 ) then do call getline ( fh , line , iostat ) if ( iostat /= 0 ) exit write ( * , '(A)' ) trim ( line ) end do else write ( * , '(A)' ) trim ( iomsg ) endif close ( fh ) end if if ( present ( exitstat )) then exitstat = stat elseif ( stat /= 0 ) then call fpm_stop ( stat , '*run*: Command ' // cmd // redirect_str // ' returned a non-zero status code' ) end if end subroutine run","tags":"","loc":"proc/run~2.html"},{"title":"warnwrite – Fortran-lang/fpm","text":"public subroutine warnwrite(fname, data) write trimmed character data to a file if it does not exist Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: fname character(len=*), intent(in) :: data (:) Source Code subroutine warnwrite ( fname , data ) character ( len =* ), intent ( in ) :: fname character ( len =* ), intent ( in ) :: data (:) if (. not . exists ( fname )) then call filewrite ( fname , data ) else write ( stderr , '(*(g0,1x))' ) ' ' , fname ,& & 'already exists. Not overwriting' endif end subroutine warnwrite","tags":"","loc":"proc/warnwrite.html"},{"title":"fpm_manifest_build – Fortran-lang/fpm","text":"Implementation of the build configuration data. A build table can currently have the following fields [build] auto-executables = bool auto-examples = bool auto-tests = bool link = [ \"lib\" ] Uses fpm_error fpm_toml fpm_strings Derived Types type, public, extends( serializable_t ) :: build_config_t Configuration data for build Components Type Visibility Attributes Name Initial logical, public :: auto_examples = .true. Automatic discovery of examples logical, public :: auto_executables = .true. Automatic discovery of executables logical, public :: auto_tests = .true. Automatic discovery of tests type( string_t ), public, allocatable :: external_modules (:) External modules to use type( string_t ), public, allocatable :: link (:) Libraries to link against logical, public :: module_naming = .false. Enforcing of package module names type( string_t ), public :: module_prefix Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => build_conf_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_build_config (self, table, package_name, error) Construct a new build configuration from a TOML data structure Read more… Arguments Type Intent Optional Attributes Name type( build_config_t ), intent(out) :: self Instance of the build configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: package_name Package name type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_build.html"},{"title":"fpm_manifest_install – Fortran-lang/fpm","text":"Implementation of the installation configuration. An install table can currently have the following fields library = bool Uses fpm_error fpm_toml Derived Types type, public, extends( serializable_t ) :: install_config_t Configuration data for installation Components Type Visibility Attributes Name Initial logical, public :: library = .false. Install library with this project Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => install_conf_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_install_config (self, table, error) Create a new installation configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( install_config_t ), intent(out) :: self Instance of the install configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_install.html"},{"title":"fpm_manifest_dependency – Fortran-lang/fpm","text":"Implementation of the meta data for dependencies. A dependency table can currently have the following fields [dependencies] \"dep1\" = { git = \"url\" } \"dep2\" = { git = \"url\" , branch = \"name\" } \"dep3\" = { git = \"url\" , tag = \"name\" } \"dep4\" = { git = \"url\" , rev = \"sha1\" } \"dep0\" = { path = \"path\" } To reduce the amount of boilerplate code this module provides two constructors\n for dependency types, one basic for an actual dependency (inline) table\n and another to collect all dependency objects from a dependencies table,\n which is handling the allocation of the objects and is forwarding the\n individual dependency tables to their respective constructors.\n The usual entry point should be the constructor for the super table. This objects contains a target to retrieve required fpm projects to\n build the target declaring the dependency.\n Resolving a dependency will result in obtaining a new package configuration\n data for the respective project. Uses fpm_toml fpm_manifest_preprocess fpm_manifest_metapackages fpm_versioning fpm_environment fpm_error fpm_strings fpm_git fpm_filesystem Interfaces public interface resize private pure subroutine resize_dependency_config(var, n) Reallocate a list of dependencies Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(inout), allocatable :: var (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size Derived Types type, public, extends( serializable_t ) :: dependency_config_t Configuration meta data for a dependency Components Type Visibility Attributes Name Initial type( git_target_t ), public, allocatable :: git Git descriptor character(len=:), public, allocatable :: name Name of the dependency character(len=:), public, allocatable :: namespace Namespace which the dependency belongs to.\nEnables multiple dependencies with the same name.\nRequired for dependencies that are obtained via the official registry. character(len=:), public, allocatable :: path Local target type( preprocess_config_t ), public, allocatable :: preprocess (:) Requested macros for the dependency type( version_t ), public, allocatable :: requested_version The requested version of the dependency.\nThe latest version is used if not specified. Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => dependency_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public function manifest_has_changed (cached, manifest, verbosity, iunit) result(has_changed) Check if two dependency configurations are different Read more… Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(in) :: cached Two instances of the dependency configuration class( dependency_config_t ), intent(in) :: manifest Two instances of the dependency configuration integer, intent(in) :: verbosity Log verbosity integer, intent(in) :: iunit Log verbosity Return Value logical Subroutines public elemental subroutine dependency_destroy (self) Clean memory Arguments Type Intent Optional Attributes Name class( dependency_config_t ), intent(inout) :: self public subroutine new_dependencies (deps, table, root, meta, error) Construct new dependency array from a TOML data structure Read more… Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(out), allocatable :: deps (:) Instance of the dependency configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( metapackage_config_t ), intent(out), optional :: meta (optional) metapackages type( error_t ), intent(out), allocatable :: error Error handling public subroutine new_dependency (self, table, root, error) Construct a new dependency configuration from a TOML data structure Read more… Arguments Type Intent Optional Attributes Name type( dependency_config_t ), intent(out) :: self Instance of the dependency configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_dependency.html"},{"title":"fpm_versioning – Fortran-lang/fpm","text":"Implementation of versioning data for comparing packages Uses fpm_error regex_module fpm_strings Interfaces public interface new_version private subroutine new_version_from_string(self, string, error) Create a new version from a string Arguments Type Intent Optional Attributes Name type( version_t ), intent(out) :: self Instance of the versioning data character(len=*), intent(in) :: string String describing the version information type( error_t ), intent(out), allocatable :: error Error handling private subroutine new_version_from_int(self, num) Create a new version from a string Arguments Type Intent Optional Attributes Name type( version_t ), intent(out) :: self Instance of the versioning data integer, intent(in) :: num (:) Subversion numbers to define version data Derived Types type, public :: version_t Type-Bound Procedures generic, public :: operator(.match.) => match ../../ Compare a version against a version constraint (x.x.0 <= v < x.x.HUGE) generic, public :: operator(/=) => not_equals generic, public :: operator(<) => less generic, public :: operator(<=) => less_equals generic, public :: operator(==) => equals generic, public :: operator(>) => greater generic, public :: operator(>=) => greater_equals procedure, public :: s ../../ Create a printable string from a version data type Functions public function regex_version_from_text (text, what, error) result(ver) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: text character(len=*), intent(in) :: what type( error_t ), intent(out), allocatable :: error Return Value type( string_t )","tags":"","loc":"module/fpm_versioning.html"},{"title":"fpm_git – Fortran-lang/fpm","text":"Implementation for interacting with git repositories. Uses fpm_error fpm_toml fpm_filesystem Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: compressed_package_name = 'compressed_package' Name of the compressed package that is generated temporarily. type( enum_descriptor ), public, parameter :: git_descriptor = enum_descriptor() Actual enumerator for descriptors character(len=*), public, parameter :: out_fmt = '(\"#\", *(1x, g0))' Common output format for writing to the command line Derived Types type, public :: enum_descriptor Possible git target Components Type Visibility Attributes Name Initial integer, public :: branch = 201 Branch in git repository integer, public :: default = 200 Default target integer, public :: error = -999 Invalid descriptor integer, public :: revision = 203 Commit hash integer, public :: tag = 202 Tag in git repository type, public, extends( serializable_t ) :: git_target_t Description of an git target Components Type Visibility Attributes Name Initial integer, public :: descriptor = git_descriptor%default Kind of the git target character(len=:), public, allocatable :: object Additional descriptor of the git object character(len=:), public, allocatable :: url Target URL of the git repository Type-Bound Procedures procedure, public :: checkout ../../ Fetch and checkout in local directory generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Show information on instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => git_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public pure function descriptor_name (descriptor) result(name) Code git descriptor to a string Arguments Type Intent Optional Attributes Name integer, intent(in) :: descriptor Return Value character(len=:), allocatable public function git_is_same (this, that) Check that two git targets are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical public function git_matches_manifest (cached, manifest, verbosity, iunit) Check that a cached dependency matches a manifest request Read more… Arguments Type Intent Optional Attributes Name type( git_target_t ), intent(in) :: cached Two input git targets type( git_target_t ), intent(in) :: manifest Two input git targets integer, intent(in) :: verbosity integer, intent(in) :: iunit Return Value logical public function git_target_branch (url, branch) result(self) Target a branch in the git repository Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: branch Name of the branch of interest Return Value type( git_target_t ) New git target public function git_target_default (url) result(self) Default target Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository Return Value type( git_target_t ) New git target public function git_target_revision (url, sha1) result(self) Target a specific git revision Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: sha1 Commit hash of interest Return Value type( git_target_t ) New git target public function git_target_tag (url, tag) result(self) Target a git tag Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: url Target URL of the git repository character(len=*), intent(in) :: tag Tag name of interest Return Value type( git_target_t ) New git target public pure function parse_descriptor (name) Parse git descriptor identifier from a string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Return Value integer Subroutines public subroutine checkout (self, local_path, error) Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target character(len=*), intent(in) :: local_path Local path to checkout in type( error_t ), intent(out), allocatable :: error Error public subroutine dump_to_toml (self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine git_archive (source, destination, ref, additional_files, verbose, error) Archive a folder using git archive . Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: source Directory to archive. character(len=*), intent(in) :: destination Destination of the archive. character(len=*), intent(in) :: ref (Symbolic) Reference to be archived. character(len=*), intent(in), optional :: additional_files (:) (Optional) list of additional untracked files to be added to the archive. logical, intent(in) :: verbose Print additional information if true. type( error_t ), intent(out), allocatable :: error Error handling. public subroutine git_revision (local_path, object, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: local_path Local path to checkout in character(len=:), intent(out), allocatable :: object Git object reference type( error_t ), intent(out), allocatable :: error Error public subroutine info (self, unit, verbosity) Show information on git target Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(in) :: self Instance of the git target integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout public subroutine load_from_toml (self, table, error) Read dependency from toml table (no checks made at this stage) Read more… Arguments Type Intent Optional Attributes Name class( git_target_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_git.html"},{"title":"fpm_installer – Fortran-lang/fpm","text":"Implementation of an installer object. The installer provides a way to install objects to their respective directories\nin the installation prefix, a generic install command allows to install\nto any directory within the prefix. Uses fpm_error fpm_filesystem iso_fortran_env fpm_environment Derived Types type, public :: installer_t Declaration of the installer type Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: bindir Binary dir relative to the installation prefix character(len=:), public, allocatable :: copy Command to copy objects into the installation prefix character(len=:), public, allocatable :: includedir Include directory relative to the installation prefix character(len=:), public, allocatable :: libdir Library directory relative to the installation prefix character(len=:), public, allocatable :: move Command to move objects into the installation prefix integer, public :: os Cached operating system character(len=:), public, allocatable :: prefix Path to installation directory integer, public :: unit = output_unit Output unit for informative printout integer, public :: verbosity = 1 Verbosity of the installer Type-Bound Procedures procedure, public :: install ../../ Install a generic file into a subdirectory in the installation prefix procedure, public :: install_executable ../../ Install an executable in its correct subdirectory procedure, public :: install_header ../../ Install a header/module in its correct subdirectory procedure, public :: install_library ../../ Install a library in its correct subdirectory procedure, public :: make_dir ../../ Create a new directory in the prefix, type-bound for unit testing purposes procedure, public :: run ../../ Run an installation command, type-bound for unit testing purposes Subroutines public subroutine new_installer (self, prefix, bindir, libdir, includedir, verbosity, copy, move) Create a new instance of an installer Arguments Type Intent Optional Attributes Name type( installer_t ), intent(out) :: self Instance of the installer character(len=*), intent(in), optional :: prefix Path to installation directory character(len=*), intent(in), optional :: bindir Binary dir relative to the installation prefix character(len=*), intent(in), optional :: libdir Library directory relative to the installation prefix character(len=*), intent(in), optional :: includedir Include directory relative to the installation prefix integer, intent(in), optional :: verbosity Verbosity of the installer character(len=*), intent(in), optional :: copy Copy command character(len=*), intent(in), optional :: move Move command","tags":"","loc":"module/fpm_installer.html"},{"title":"fpm_manifest – Fortran-lang/fpm","text":"Package configuration data. This module provides the necessary procedure to translate a TOML document\nto the corresponding Fortran type, while verifying it with respect to\nits schema. Additionally, the required data types for users of this module are reexported\nto hide the actual implementation details. Uses fpm_manifest_example fpm_environment fpm_toml fpm_manifest_dependency fpm_filesystem fpm_manifest_preprocess fpm_error fpm_strings fpm_manifest_executable fpm_manifest_test fpm_manifest_library fpm_manifest_package Subroutines public subroutine default_example (self, name) Populate test in case we find the default example/ directory Arguments Type Intent Optional Attributes Name type( example_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package public subroutine default_executable (self, name) Populate executable in case we find the default app directory Arguments Type Intent Optional Attributes Name type( executable_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package public subroutine default_library (self) Populate library in case we find the default src directory Arguments Type Intent Optional Attributes Name type( library_config_t ), intent(out) :: self Instance of the library meta data public subroutine default_test (self, name) Populate test in case we find the default test/ directory Arguments Type Intent Optional Attributes Name type( test_config_t ), intent(out) :: self Instance of the executable meta data character(len=*), intent(in) :: name Name of the package public subroutine get_package_data (package, file, error, apply_defaults) Obtain package meta data from a configuation file Arguments Type Intent Optional Attributes Name type( package_config_t ), intent(out) :: package Parsed package meta data character(len=*), intent(in) :: file Name of the package configuration file type( error_t ), intent(out), allocatable :: error Error status of the operation logical, intent(in), optional :: apply_defaults Apply package defaults (uses file system operations)","tags":"","loc":"module/fpm_manifest.html"},{"title":"fpm_manifest_package – Fortran-lang/fpm","text":"Define the package data containing the meta data from the configuration file. The package data defines a Fortran type corresponding to the respective\n TOML document, after creating it from a package file no more interaction\n with the TOML document is required. Every configuration type provides it custom constructor (prefixed with new_ )\n and knows how to deserialize itself from a TOML document.\n To ensure we find no untracked content in the package file all keywords are\n checked and possible entries have to be explicitly allowed in the check function.\n If entries are mutally exclusive or interdependent inside the current table\n the check function is required to enforce this schema on the data structure. The package file root allows the following keywords name = \"string\" version = \"string\" license = \"string\" author = \"string\" maintainer = \"string\" copyright = \"string\" [library] [dependencies] [dev-dependencies] [profiles] [build] [install] [fortran] [[ executable ]] [[ example ]] [[ test ]] [extra] Uses fpm_manifest_build fpm_manifest_example fpm_manifest_profile fpm_toml fpm_manifest_dependency fpm_manifest_preprocess fpm_manifest_metapackages fpm_manifest_fortran fpm_versioning fpm_manifest_install fpm_error fpm_manifest_executable fpm_manifest_test fpm_manifest_library fpm_filesystem Derived Types type, public, extends( serializable_t ) :: package_config_t Package meta data Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: author Author meta data type( build_config_t ), public :: build Build configuration data character(len=:), public, allocatable :: copyright Copyright meta data type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data type( dependency_config_t ), public, allocatable :: dev_dependency (:) Development dependency meta data type( example_config_t ), public, allocatable :: example (:) Example meta data type( executable_config_t ), public, allocatable :: executable (:) Executable meta data type( fortran_config_t ), public :: fortran Fortran meta data type( install_config_t ), public :: install Installation configuration data type( library_config_t ), public, allocatable :: library Library meta data character(len=:), public, allocatable :: license License meta data character(len=:), public, allocatable :: maintainer Maintainer meta data type( metapackage_config_t ), public :: meta Metapackage data character(len=:), public, allocatable :: name Name of the package type( preprocess_config_t ), public, allocatable :: preprocess (:) Preprocess meta data type( profile_config_t ), public, allocatable :: profiles (:) Profiles meta data type( test_config_t ), public, allocatable :: test (:) Test meta data type( version_t ), public :: version Package version Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => manifest_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_package (self, table, root, error) Construct a new package configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( package_config_t ), intent(out) :: self Instance of the package configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in), optional :: root Root directory of the manifest type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_package.html"},{"title":"fpm_toml – Fortran-lang/fpm","text":"Interface to TOML processing library This module acts as a proxy to the toml-f public Fortran API and allows\n to selectively expose components from the library to fpm .\n The interaction with toml-f data types outside of this module should be\n limited to tables, arrays and key-lists, most of the necessary interactions\n are implemented in the building interface with the get_value and set_value procedures. This module allows to implement features necessary for fpm , which are\n not yet available in upstream toml-f . For more details on the library used see the TOML-Fortran developer pages. Uses jonquil tomlf iso_fortran_env tomlf_de_parser fpm_strings fpm_error Interfaces public interface add_table add_table: fpm interface private subroutine add_table_fpm(table, key, ptr, error, whereAt) Function wrapper to add a toml table and return an fpm error Nullify pointer Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key Table key type(toml_table), intent(out), pointer :: ptr The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description public interface get_value get_value: fpm interface private subroutine get_logical(table, key, var, error, whereAt) Function wrapper to get a logical variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key logical, intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine get_integer(table, key, var, error, whereAt) Function wrapper to get a default integer variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer, intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine get_integer_64(table, key, var, error, whereAt) Function wrapper to get a integer(int64) variable from a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer(kind=int64), intent(inout) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description public interface set_string private subroutine set_character(table, key, var, error, whereAt) Function wrapper to set a character(len=:), allocatable variable to a toml table Check the key is not empty Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key List of keys to check. character(len=*), intent(in), optional :: var The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_string_type(table, key, var, error, whereAt) Function wrapper to set a character(len=:), allocatable variable to a toml table Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key List of keys to check. type( string_t ), intent(in) :: var The character variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description public interface set_value set_value: fpm interface private subroutine set_logical(table, key, var, error, whereAt) Function wrapper to set a logical variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key logical, intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_integer(table, key, var, error, whereAt) Function wrapper to set a default integer variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer, intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description private subroutine set_integer_64(table, key, var, error, whereAt) Function wrapper to set a default integer variable to a toml table, returning an fpm error Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key The key integer(kind=int64), intent(in) :: var The variable type( error_t ), intent(out), allocatable :: error Error handling character(len=*), intent(in), optional :: whereAt Optional description Derived Types type, public, abstract :: serializable_t An abstract interface for any fpm class that should be fully serializable to/from TOML/JSON Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure(to_toml), public, deferred :: dump_to_toml ../../ Dump to TOML table, unit, file generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure(from_toml), public, deferred :: load_from_toml ../../ Load from TOML table, unit, file generic, public :: operator(==) => serializable_is_same procedure(is_equal), public, deferred :: serializable_is_same ../../ Serializable entities need a way to check that they’re equal procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public function name_is_json (filename) Choose between JSON or TOML based on a file name Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value logical Subroutines public subroutine check_keys (table, valid_keys, error) Check if table contains only keys that are part of the list. If a key is\nfound that is not part of the list, an error is allocated. Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: valid_keys (:) List of keys to check. type( error_t ), intent(out), allocatable :: error Error handling public subroutine get_list (table, key, list, error) Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the TOML data structure character(len=*), intent(in) :: key Key to read from type( string_t ), intent(out), allocatable :: list (:) List of strings to read type( error_t ), intent(out), allocatable :: error Error handling public subroutine read_package_file (table, manifest, error) Process the configuration file to a TOML data structure Arguments Type Intent Optional Attributes Name type(toml_table), intent(out), allocatable :: table TOML data structure character(len=*), intent(in) :: manifest Name of the package configuration file type( error_t ), intent(out), allocatable :: error Error status of the operation public subroutine set_list (table, key, list, error) Set no key if array is not present Read more… Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout) :: table Instance of the toml table character(len=*), intent(in) :: key Key to save to type( string_t ), intent(in), allocatable :: list (:) Instance of the string array type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_toml.html"},{"title":"fpm_cmd_install – Fortran-lang/fpm","text":"Uses fpm_installer fpm_targets iso_fortran_env fpm_backend fpm fpm_command_line fpm_manifest fpm_model fpm_strings fpm_error fpm_filesystem Subroutines public subroutine cmd_install (settings) Entry point for the fpm-install subcommand Arguments Type Intent Optional Attributes Name type( fpm_install_settings ), intent(inout) :: settings Representation of the command line settings","tags":"","loc":"module/fpm_cmd_install.html"},{"title":"fpm_manifest_profile – Fortran-lang/fpm","text":"Implementation of the meta data for compiler flag profiles. A profiles table can currently have the following subtables:\n Profile names - any string, if omitted, flags are appended to all matching profiles\n Compiler - any from the following list, omitting it yields an error “gfortran” “ifort” “ifx” “pgfortran” “nvfortran” “flang” “caf” “f95” “lfortran” “lfc” “nagfor” “crayftn” “xlf90” “ftn95” OS - any from the following list, if omitted, the profile is used if and only\n if there is no profile perfectly matching the current configuration “linux” “macos” “windows” “cygwin” “solaris” “freebsd” “openbsd” “unknown” Each of the subtables currently supports the following fields: [profiles.debug.gfortran.linux] flags = \"-Wall -g -Og\" c-flags = \"-g O1\" cxx-flags = \"-g O1\" link-time-flags = \"-xlinkopt\" files = { \"hello_world.f90\" = \"-Wall -O3\" } Uses fpm_toml fpm_environment fpm_error fpm_strings fpm_filesystem Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: DEFAULT_COMPILER = 'gfortran' Name of the default compiler integer, public, parameter :: OS_ALL = -1 character(len=:), public, allocatable :: path Derived Types type, public, extends( serializable_t ) :: file_scope_flag Type storing file name - file scope compiler flags pairs Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: file_name Name of the file character(len=:), public, allocatable :: flags File scope flags Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => file_scope_dump generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => file_scope_load generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => file_scope_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: profile_config_t Configuration meta data for a profile Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: c_flags C compiler flags character(len=:), public, allocatable :: compiler Name of the compiler character(len=:), public, allocatable :: cxx_flags C++ compiler flags type( file_scope_flag ), public, allocatable :: file_scope_flags (:) File scope flags character(len=:), public, allocatable :: flags Fortran compiler flags logical, public :: is_built_in = .false. Is this profile one of the built-in ones? character(len=:), public, allocatable :: link_time_flags Link time compiler flags integer, public :: os_type = OS_ALL Value repesenting OS character(len=:), public, allocatable :: profile_name Name of the profile Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => profile_dump procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => profile_load generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => profile_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public function file_scope_same (this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical public function get_default_profiles (error) result(default_profiles) Construct an array of built-in profiles Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Error handling Return Value type( profile_config_t ), allocatable, (:) public function info_profile (profile) result(s) Print a representation of profile_config_t Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(in) :: profile Profile to be represented Return Value character(len=:), allocatable String representation of given profile public function new_profile (profile_name, compiler, os_type, flags, c_flags, cxx_flags, link_time_flags, file_scope_flags, is_built_in) result(profile) Construct a new profile configuration from a TOML data structure Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: profile_name Name of the profile character(len=*), intent(in) :: compiler Name of the compiler integer, intent(in) :: os_type Type of the OS character(len=*), intent(in), optional :: flags Fortran compiler flags character(len=*), intent(in), optional :: c_flags C compiler flags character(len=*), intent(in), optional :: cxx_flags C++ compiler flags character(len=*), intent(in), optional :: link_time_flags Link time compiler flags type( file_scope_flag ), intent(in), optional :: file_scope_flags (:) File scope flags logical, intent(in), optional :: is_built_in Is this profile one of the built-in ones? Return Value type( profile_config_t ) public function os_type_name (os_type) Match lowercase string with name of OS to os_type enum Arguments Type Intent Optional Attributes Name integer, intent(in) :: os_type Enum representing type of OS Return Value character(len=:), allocatable Name of operating system public function profile_same (this, that) All checks passed! Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical Subroutines public subroutine file_scope_dump (self, table, error) Dump to toml table Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine file_scope_load (self, table, error) Read from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( file_scope_flag ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine find_profile (profiles, profile_name, compiler, os_type, found_matching, chosen_profile) Look for profile with given configuration in array profiles Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(in), allocatable :: profiles (:) Array of profiles character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler Name of compiler integer, intent(in) :: os_type Type of operating system (enum) logical, intent(out) :: found_matching Boolean value containing true if matching profile was found type( profile_config_t ), intent(out) :: chosen_profile Last matching profile in the profiles array public subroutine get_flags (profile_name, compiler_name, os_type, key_list, table, profiles, profindex, os_valid) Look for flags, c-flags, link-time-flags key-val pairs\nand files table in a given table and create new profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler integer, intent(in) :: os_type OS type type(toml_key), intent(in), allocatable :: key_list (:) List of keys in the table type(toml_table), intent(in), pointer :: table Table containing OS tables type( profile_config_t ), intent(inout), allocatable :: profiles (:) List of profiles integer, intent(inout) :: profindex Index in the list of profiles logical, intent(in) :: os_valid Was called with valid operating system public subroutine info (self, unit, verbosity) Write information on instance Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(in) :: self Instance of the profile configuration integer, intent(in) :: unit Unit for IO integer, intent(in), optional :: verbosity Verbosity of the printout public subroutine match_os_type (os_name, os_type) Match os_type enum to a lowercase string with name of OS Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: os_name Name of operating system integer, intent(out) :: os_type Enum representing type of OS public subroutine new_profiles (profiles, table, error) Construct new profiles array from a TOML data structure Arguments Type Intent Optional Attributes Name type( profile_config_t ), intent(out), allocatable :: profiles (:) Instance of the dependency configuration type(toml_table), intent(inout), target :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine profile_dump (self, table, error) Dump to toml table Read more… Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine profile_load (self, table, error) Read from toml table (no checks made at this stage) Read more… Arguments Type Intent Optional Attributes Name class( profile_config_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine traverse_compilers (profile_name, comp_list, table, error, profiles_size, profiles, profindex) Traverse compiler tables Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile type(toml_key), intent(in), allocatable :: comp_list (:) List of OSs in table with profile name given type(toml_table), intent(in), pointer :: table Table containing compiler tables type( error_t ), intent(out), allocatable :: error Error handling integer, intent(inout), optional :: profiles_size Number of profiles in list of profiles type( profile_config_t ), intent(inout), optional, allocatable :: profiles (:) List of profiles integer, intent(inout), optional :: profindex Index in the list of profiles public subroutine traverse_oss (profile_name, compiler_name, os_list, table, profiles, profindex, error) Traverse operating system tables to obtain profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: os_list (:) List of OSs in table with profile name and compiler name given type(toml_table), intent(in), pointer :: table Table containing OS tables type( profile_config_t ), intent(inout), allocatable :: profiles (:) List of profiles integer, intent(inout) :: profindex Index in the list of profiles type( error_t ), intent(out), allocatable :: error Error handling public subroutine traverse_oss_for_size (profile_name, compiler_name, os_list, table, profiles_size, error) Traverse operating system tables to obtain number of profiles Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: os_list (:) List of OSs in table with profile name and compiler name given type(toml_table), intent(in), pointer :: table Table containing OS tables integer, intent(inout) :: profiles_size Number of profiles in list of profiles type( error_t ), intent(out), allocatable :: error Error handling public subroutine validate_compiler_name (compiler_name, is_valid) Check if compiler name is a valid compiler name Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: compiler_name Name of a compiler logical, intent(out) :: is_valid Boolean value of whether compiler_name is valid or not public subroutine validate_os_name (os_name, is_valid) Check if os_name is a valid name of a supported OS Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: os_name Name of an operating system logical, intent(out) :: is_valid Boolean value of whether os_name is valid or not public subroutine validate_profile_table (profile_name, compiler_name, key_list, table, error, os_valid) Arguments Type Intent Optional Attributes Name character(len=:), intent(in), allocatable :: profile_name Name of profile character(len=:), intent(in), allocatable :: compiler_name Name of compiler type(toml_key), intent(in), allocatable :: key_list (:) List of keys in the table type(toml_table), intent(in), pointer :: table Table containing OS tables type( error_t ), intent(out), allocatable :: error Error handling logical, intent(in) :: os_valid Was called with valid operating system","tags":"","loc":"module/fpm_manifest_profile.html"},{"title":"fpm_backend_output – Fortran-lang/fpm","text":"Build Backend Progress Output This module provides a derived type build_progress_t for printing build status\n and progress messages to the console while the backend is building the package. The build_progress_t type supports two modes: normal and plain where the former does ‘pretty’ output and the latter does not.\n The normal mode is intended for typical interactive usage whereas\n ‘plain’ mode is used with the --verbose flag or when stdout is not attached\n to a terminal (e.g. when piping or redirecting stdout ). In these cases,\n the pretty output must be suppressed to avoid control codes being output. Uses fpm_targets iso_fortran_env fpm_backend_console fpm_filesystem Interfaces public interface build_progress_t Constructor for build_progress_t private function new_build_progress(target_queue, plain_mode) result(progress) Initialise a new build progress object Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in), target :: target_queue (:) The queue of scheduled targets logical, intent(in), optional :: plain_mode Enable ‘plain’ output for progress object Return Value type( build_progress_t ) Progress object to initialise Derived Types type, public :: build_progress_t Build progress object Components Type Visibility Attributes Name Initial type( console_t ), public :: console Console object for updating console lines integer, public :: n_complete Number of completed targets integer, public :: n_target Total number of targets scheduled integer, public, allocatable :: output_lines (:) Store needed when updating previous console lines logical, public :: plain_mode = .true. ‘Plain’ output (no colors or updating) type( build_target_ptr ), public, pointer :: target_queue (:) Queue of scheduled build targets Constructor Constructor for build_progress_t private\n\n \n function new_build_progress (target_queue, plain_mode) Initialise a new build progress object Type-Bound Procedures procedure, public :: compiling_status => output_status_compiling ../../ Output ‘compiling’ status for build target procedure, public :: completed_status => output_status_complete ../../ Output ‘complete’ status for build target procedure, public :: success => output_progress_success ../../ Output finished status for whole package","tags":"","loc":"module/fpm_backend_output.html"},{"title":"fpm_targets – Fortran-lang/fpm","text":"Build target handling This module handles the construction of the build target list\n from the sources list ( [[targets_from_sources]] ), the\n resolution of module-dependencies between build targets\n ( [[resolve_module_dependencies]] ), and the enumeration of\n objects required for link targets ( [[resolve_target_linking]] ). A build target ( [[build_target_t]] ) is a file to be generated\n by the backend (compilation and linking). @note Note\n The current implementation is ignorant to the existence of\n module files ( .mod , .smod ). Dependencies arising from modules\n are based on the corresponding object files ( .o ) only. For more information, please read the documentation for the procedures: [[build_target_list]] [[resolve_module_dependencies]] Enumerations Target type: FPM_TARGET_* Describes the type of build target — determines backend build rules Uses iso_fortran_env fpm_sources fpm_manifest_preprocess fpm_model fpm_environment fpm_error fpm_compiler fpm_strings fpm_filesystem Variables Type Visibility Attributes Name Initial integer, public, parameter :: FPM_TARGET_ARCHIVE = 2 Target type is library archive integer, public, parameter :: FPM_TARGET_CPP_OBJECT = 5 Target type is cpp compiled object integer, public, parameter :: FPM_TARGET_C_OBJECT = 4 Target type is c compiled object integer, public, parameter :: FPM_TARGET_EXECUTABLE = 1 Target type is executable integer, public, parameter :: FPM_TARGET_OBJECT = 3 Target type is compiled object integer, public, parameter :: FPM_TARGET_UNKNOWN = -1 Target type is unknown (ignored) Derived Types type, public :: build_target_ptr Wrapper type for constructing arrays of [[build_target_t]] pointers Components Type Visibility Attributes Name Initial type( build_target_t ), public, pointer :: ptr => null() type, public :: build_target_t Type describing a generated build target Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: compile_flags Compile flags for this build target type( build_target_ptr ), public, allocatable :: dependencies (:) Resolved build dependencies integer(kind=int64), public, allocatable :: digest_cached Previous source file hash type( fortran_features_t ), public :: features Language features character(len=:), public, allocatable :: link_flags Link flags for this build target type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public, allocatable :: link_objects (:) Objects needed to link this target type( string_t ), public, allocatable :: macros (:) List of macros character(len=:), public, allocatable :: output_dir File path of output directory character(len=:), public, allocatable :: output_file File path of build target object relative to cwd character(len=:), public, allocatable :: output_log_file File path of build log file relative to cwd character(len=:), public, allocatable :: output_name File path of build target object relative to output_dir character(len=:), public, allocatable :: package_name Name of parent package integer, public :: schedule = -1 Targets in the same schedule group are guaranteed to be independent logical, public :: skip = .false. Flag set if build target will be skipped (not built) logical, public :: sorted = .false. Flag set if build target is sorted for building type( srcfile_t ), public, allocatable :: source Primary source for this build target integer, public :: target_type = FPM_TARGET_UNKNOWN Target type logical, public :: touched = .false. Flag set when first visited to check for circular dependencies character(len=:), public, allocatable :: version Version number Type-Bound Procedures procedure, public :: is_executable_target Functions public pure function FPM_TARGET_NAME (type) result(msg) Target type name Arguments Type Intent Optional Attributes Name integer, intent(in) :: type Return Value character(len=:), allocatable Subroutines public subroutine add_dependency (target, dependency) Add pointer to dependeny in target%dependencies Arguments Type Intent Optional Attributes Name type( build_target_t ), intent(inout) :: target type( build_target_t ), intent(in), target :: dependency public subroutine add_target (targets, package, type, output_name, source, link_libraries, features, preprocess, version) Allocate a new target and append to target list Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout), allocatable :: targets (:) character(len=*), intent(in) :: package integer, intent(in) :: type character(len=*), intent(in) :: output_name type( srcfile_t ), intent(in), optional :: source type( string_t ), intent(in), optional :: link_libraries (:) type( fortran_features_t ), intent(in), optional :: features type( preprocess_config_t ), intent(in), optional :: preprocess character(len=*), intent(in), optional :: version public subroutine filter_executable_targets (targets, scope, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) integer, intent(in) :: scope type( string_t ), intent(out), allocatable :: list (:) public subroutine filter_library_targets (targets, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) type( string_t ), intent(out), allocatable :: list (:) public subroutine filter_modules (targets, list) Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(in) :: targets (:) type( string_t ), intent(out), allocatable :: list (:) public subroutine resolve_module_dependencies (targets, external_modules, error) Add dependencies to source-based targets ( FPM_TARGET_OBJECT )\n based on any modules used by the corresponding source file. Read more… Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout), target :: targets (:) type( string_t ), intent(in) :: external_modules (:) type( error_t ), intent(out), allocatable :: error public subroutine targets_from_sources (targets, model, prune, error) High-level wrapper to generate build target information Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(out), allocatable :: targets (:) The generated list of build targets type( fpm_model_t ), intent(inout), target :: model The package model from which to construct the target list logical, intent(in) :: prune Enable tree-shaking/pruning of module dependencies type( error_t ), intent(out), allocatable :: error Error structure","tags":"","loc":"module/fpm_targets.html"},{"title":"fpm_sources – Fortran-lang/fpm","text":"Discovery of sources This module implements subroutines for building a list of [[srcfile_t]] objects by looking for source files in the filesystem. Uses fpm_manifest_executable fpm_model fpm_environment fpm_error fpm_source_parsing fpm_strings fpm_filesystem Functions public function get_exe_name_with_suffix (source) result(suffixed) Build an executable name with suffix. Safe routine that always returns an allocated string Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(in) :: source Return Value character(len=:), allocatable Subroutines public subroutine add_executable_sources (sources, executables, scope, auto_discover, with_f_ext, error) Add to sources using the executable and test entries in the manifest and\napplies any executable-specific overrides such as executable%name .\nAdds all sources (including modules) from each executable%source_dir Compare lowercase strings to allow auto-discovery of pre-processed extensions Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(inout), allocatable, target :: sources (:) List of [[srcfile_t]] objects to append to. Allocated if not allocated class( executable_config_t ), intent(in) :: executables (:) List of [[executable_config_t]] entries from manifest integer, intent(in) :: scope Scope to apply to the discovered sources: either FPM_SCOPE_APP or FPM_SCOPE_TEST , see fpm_model logical, intent(in) :: auto_discover If .false. only executables and tests specified in the manifest are added to sources type( string_t ), intent(in), optional :: with_f_ext (:) Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type( error_t ), intent(out), allocatable :: error Error handling public subroutine add_sources_from_dir (sources, directory, scope, with_executables, with_f_ext, recurse, error) Add to sources by looking for source files in directory Arguments Type Intent Optional Attributes Name type( srcfile_t ), intent(inout), allocatable, target :: sources (:) List of [[srcfile_t]] objects to append to. Allocated if not allocated character(len=*), intent(in) :: directory Directory in which to search for source files integer, intent(in) :: scope Scope to apply to the discovered sources, see fpm_model for enumeration logical, intent(in), optional :: with_executables Executable sources (fortran program s) are ignored unless with_executables=.true. type( string_t ), intent(in), optional :: with_f_ext (:) Additional user-defined (preprocessor) extensions that should be treated as Fortran sources logical, intent(in), optional :: recurse Whether to recursively search subdirectories, default is .true. type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_sources.html"},{"title":"fpm_command_line – Fortran-lang/fpm","text":"Definition of the command line interface This module uses M_CLI2 to define\n the command line interface.\n To define a command line interface create a new command settings type\n from the fpm_cmd_settings base class or the respective parent command\n settings. The subcommand is selected by the first non-option argument in the command\n line. In the subcase block the actual command line is defined and transferred\n to an instance of the fpm_cmd_settings , the actual type is used by the fpm main program to determine which command entry point is chosen. To add a new subcommand add a new case to select construct and specify the\n wanted command line and the expected default values.\n Some of the following points also apply if you add a new option or argument\n to an existing fpm subcommand.\n At this point you should create a help page for the new command in a simple\n catman-like format as well in the set_help procedure.\n Make sure to register new subcommands in the fpm-manual command by adding\n them to the manual character array and in the help/manual case as well.\n You should add the new command to the synopsis section of the fpm-list , fpm-help and fpm --list help pages below to make sure the help output\n is complete and consistent as well. Uses fpm_environment fpm_release iso_fortran_env fpm_os fpm_strings M_CLI2 fpm_error fpm_filesystem Derived Types type, public, extends( fpm_cmd_settings ) :: fpm_build_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_cmd_settings ) :: fpm_clean_settings Components Type Visibility Attributes Name Initial logical, public :: clean_all = .false. logical, public :: clean_skip = .false. logical, public :: registry_cache = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, abstract :: fpm_cmd_settings Components Type Visibility Attributes Name Initial logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_build_settings ) :: fpm_export_settings Settings for exporting model data Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: dump_dependencies character(len=:), public, allocatable :: dump_manifest character(len=:), public, allocatable :: dump_model character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_build_settings ) :: fpm_install_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: bindir logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: includedir character(len=:), public, allocatable :: ldflag character(len=:), public, allocatable :: libdir logical, public :: list = .false. logical, public :: no_rebuild character(len=:), public, allocatable :: prefix character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_cmd_settings ) :: fpm_new_settings Components Type Visibility Attributes Name Initial logical, public :: backfill = .true. character(len=:), public, allocatable :: name logical, public :: verbose = .true. logical, public :: with_bare = .false. logical, public :: with_example = .false. logical, public :: with_executable = .false. logical, public :: with_full = .false. logical, public :: with_lib = .true. logical, public :: with_test = .false. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_build_settings ) :: fpm_publish_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump character(len=:), public, allocatable :: flag logical, public :: is_dry_run = .false. character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=:), public, allocatable :: profile logical, public :: prune = .true. logical, public :: show_model = .false. logical, public :: show_package_version = .false. logical, public :: show_upload_data = .false. character(len=:), public, allocatable :: token logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir type, public, extends( fpm_build_settings ) :: fpm_run_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: args logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump logical, public :: example character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=ibug), public, allocatable :: name (:) character(len=:), public, allocatable :: profile logical, public :: prune = .true. character(len=:), public, allocatable :: runner character(len=:), public, allocatable :: runner_args logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Type-Bound Procedures procedure, public :: name_ID procedure, public :: runner_command type, public, extends( fpm_run_settings ) :: fpm_test_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: archiver character(len=:), public, allocatable :: args logical, public :: build_tests = .false. character(len=:), public, allocatable :: c_compiler character(len=:), public, allocatable :: cflag character(len=:), public, allocatable :: compiler character(len=:), public, allocatable :: cxx_compiler character(len=:), public, allocatable :: cxxflag character(len=:), public, allocatable :: dump logical, public :: example character(len=:), public, allocatable :: flag character(len=:), public, allocatable :: ldflag logical, public :: list = .false. character(len=ibug), public, allocatable :: name (:) character(len=:), public, allocatable :: profile logical, public :: prune = .true. character(len=:), public, allocatable :: runner character(len=:), public, allocatable :: runner_args logical, public :: show_model = .false. logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Type-Bound Procedures procedure, public :: name_ID procedure, public :: runner_command type, public, extends( fpm_cmd_settings ) :: fpm_update_settings Settings for interacting and updating with project dependencies Components Type Visibility Attributes Name Initial logical, public :: clean character(len=:), public, allocatable :: dump logical, public :: fetch_only character(len=ibug), public, allocatable :: name (:) logical, public :: verbose = .true. character(len=:), public, allocatable :: working_dir Functions public function get_fpm_env (env, default) result(val) Get an environment variable for fpm, this routine ensures that every variable\nused by fpm is prefixed with FPM_. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: env character(len=*), intent(in) :: default Return Value character(len=:), allocatable Subroutines public subroutine get_command_line_settings (cmd_settings) ! canon_path is not converting “.”, etc.\n& ‘ unknown help topic “’//trim(unnamed(i)).’not found in:’,manual] Arguments Type Intent Optional Attributes Name class( fpm_cmd_settings ), intent(out), allocatable :: cmd_settings","tags":"","loc":"module/fpm_command_line.html"},{"title":"fpm_cmd_update – Fortran-lang/fpm","text":"Uses fpm_toml fpm_command_line fpm_manifest fpm_dependency fpm_error fpm_filesystem Subroutines public subroutine cmd_update (settings) Entry point for the update subcommand Arguments Type Intent Optional Attributes Name type( fpm_update_settings ), intent(in) :: settings Representation of the command line arguments","tags":"","loc":"module/fpm_cmd_update.html"},{"title":"fpm_cmd_export – Fortran-lang/fpm","text":"Uses fpm_toml fpm fpm_command_line fpm_manifest fpm_dependency fpm_model fpm_error fpm_filesystem Subroutines public subroutine cmd_export (settings) Entry point for the export subcommand\nRead in manifest\nExport manifest\nExport dependency tree Read more… Arguments Type Intent Optional Attributes Name type( fpm_export_settings ), intent(inout) :: settings Representation of the command line arguments","tags":"","loc":"module/fpm_cmd_export.html"},{"title":"fpm_downloader – Fortran-lang/fpm","text":"Uses jonquil fpm_versioning fpm_strings fpm_error fpm_filesystem Derived Types type, public :: downloader_t This type could be entirely avoided but it is quite practical because it can be mocked for testing. Type-Bound Procedures procedure, public, nopass :: get_file procedure, public, nopass :: get_pkg_data procedure, public, nopass :: unpack procedure, public, nopass :: upload_form","tags":"","loc":"module/fpm_downloader.html"},{"title":"fpm_dependency – Fortran-lang/fpm","text":"Dependency management Fetching dependencies and creating a dependency tree Dependencies on the top-level can be specified from: package%dependencies package%dev_dependencies package%executable(:)%dependencies package%test(:)%dependencies Each dependency is fetched in some way and provides a path to its package\nmanifest.\nThe package%dependencies of the dependencies are resolved recursively. To initialize the dependency tree all dependencies are recursively fetched\nand stored in a flat data structure to avoid retrieving a package twice.\nThe data structure used to store this information should describe the current\nstatus of the dependency tree. Important information are: name of the package version of the package path to the package root Additionally, for version controlled dependencies the following should be\nstored along with the package: the upstream url the current checked out revision Fetching a remote (version controlled) dependency turns it for our purpose\ninto a local path dependency which is handled by the same means. Updating dependencies For a given dependency tree all top-level dependencies can be updated.\nWe have two cases to consider, a remote dependency and a local dependency,\nagain, remote dependencies turn into local dependencies by fetching.\nTherefore we will update remote dependencies by simply refetching them. For remote dependencies we have to refetch if the revision in the manifest\nchanges or the upstream HEAD has changed (for branches and tags). Note For our purpose a tag is just a fancy branch name. Tags can be delete and\n modified afterwards, therefore they do not differ too much from branches\n from our perspective. For the latter case we only know if we actually fetch from the upstream URL. In case of local (and fetched remote) dependencies we have to read the package\nmanifest and compare its dependencies against our dependency tree, any change\nrequires updating the respective dependencies as well. Handling dependency compatibilties Currenly ignored. First come, first serve. Uses jonquil iso_fortran_env fpm_settings fpm_toml fpm_manifest_dependency fpm_downloader fpm_manifest fpm_versioning fpm_environment fpm_error fpm_strings fpm_manifest_preprocess fpm_git fpm_filesystem Interfaces public interface resize Overloaded reallocation interface private pure subroutine resize_dependency_node(var, n) Reallocate a list of dependencies Arguments Type Intent Optional Attributes Name type( dependency_node_t ), intent(inout), allocatable :: var (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size Derived Types type, public, extends( dependency_config_t ) :: dependency_node_t Dependency node in the projects dependency tree Components Type Visibility Attributes Name Initial logical, public :: cached = .false. Dependency was loaded from a cache logical, public :: done = .false. Dependency is handled type( git_target_t ), public, allocatable :: git Git descriptor character(len=:), public, allocatable :: name Name of the dependency character(len=:), public, allocatable :: namespace Namespace which the dependency belongs to.\nEnables multiple dependencies with the same name.\nRequired for dependencies that are obtained via the official registry. character(len=:), public, allocatable :: path Local target type( preprocess_config_t ), public, allocatable :: preprocess (:) Requested macros for the dependency character(len=:), public, allocatable :: proj_dir Installation prefix of this dependencies type( version_t ), public, allocatable :: requested_version The requested version of the dependency.\nThe latest version is used if not specified. character(len=:), public, allocatable :: revision Checked out revision of the version control system logical, public :: update = .false. Dependency should be updated type( version_t ), public, allocatable :: version Actual version of this dependency Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => node_dump_to_toml procedure, public :: get_from_registry ../../ Get dependency from the registry. procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => node_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: register ../../ Update dependency from project manifest. procedure, public :: serializable_is_same => dependency_node_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: dependency_tree_t Respresentation of a projects dependencies Read more… Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: cache Cache file type( dependency_node_t ), public, allocatable :: dep (:) Flattend list of all dependencies character(len=:), public, allocatable :: dep_dir Installation prefix for dependencies integer, public :: ndep = 0 Number of currently registered dependencies integer, public :: unit = output_unit Unit for IO integer, public :: verbosity = 1 Verbosity of printout Type-Bound Procedures generic, public :: add => add_project, add_project_dependencies, add_dependencies, add_dependency, add_dependency_node ../../ Overload procedure to add new dependencies to the tree generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit generic, public :: dump_cache => dump_cache_to_file, dump_cache_to_unit, dump_cache_to_toml ../../ Writing of dependency tree procedure, public :: dump_to_toml => tree_dump_to_toml generic, public :: find => find_name ../../ Find a dependency in the tree procedure, public :: finished ../../ Depedendncy resolution finished generic, public :: has => has_dependency ../../ True if entity can be found generic, public :: load => load_from_toml , load_from_file, load_from_unit generic, public :: load_cache => load_cache_from_file, load_cache_from_unit, load_cache_from_toml ../../ Reading of dependency tree procedure, public :: load_from_toml => tree_load_from_toml generic, public :: operator(==) => serializable_is_same generic, public :: resolve => resolve_dependencies, resolve_dependency ../../ Resolve dependencies procedure, public :: serializable_is_same => dependency_tree_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip generic, public :: update => update_dependency, update_tree ../../ Update dependency tree Subroutines public subroutine check_and_read_pkg_data (json, node, download_url, version, error) Arguments Type Intent Optional Attributes Name type(json_object), intent(inout) :: json class( dependency_node_t ), intent(in) :: node character(len=:), intent(out), allocatable :: download_url type( version_t ), intent(out) :: version type( error_t ), intent(out), allocatable :: error public elemental subroutine destroy_dependency_node (self) Destructor Arguments Type Intent Optional Attributes Name class( dependency_node_t ), intent(inout) :: self public subroutine new_dependency_node (self, dependency, version, proj_dir, update) Create a new dependency node from a configuration Arguments Type Intent Optional Attributes Name type( dependency_node_t ), intent(out) :: self Instance of the dependency node type( dependency_config_t ), intent(in) :: dependency Dependency configuration data type( version_t ), intent(in), optional :: version Version of the dependency character(len=*), intent(in), optional :: proj_dir Installation prefix of the dependency logical, intent(in), optional :: update Dependency should be updated public subroutine new_dependency_tree (self, verbosity, cache) Create a new dependency tree Arguments Type Intent Optional Attributes Name type( dependency_tree_t ), intent(out) :: self Instance of the dependency tree integer, intent(in), optional :: verbosity Verbosity of printout character(len=*), intent(in), optional :: cache Name of the cache file","tags":"","loc":"module/fpm_dependency.html"},{"title":"fpm_pkg_config – Fortran-lang/fpm","text":"The fpm interface to pkg-config This module contains wrapper functions to interface with a pkg-config installation. Uses fpm_environment fpm_error fpm_strings shlex_module fpm_filesystem Functions public function assert_pkg_config () Check whether pkg-config is available on the local system Arguments None Return Value logical public function pkgcfg_get_build_flags (name, allow_system, error) result(flags) Get build flags (option to include flags from system directories, that \ngfortran does not look into by default) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Package name logical, intent(in) :: allow_system Should pkg-config look in system paths? This is necessary for gfortran \nthat doesn’t otherwise look into them type( error_t ), intent(out), allocatable :: error Error flag Return Value type( string_t ), allocatable, (:) List of compile flags public function pkgcfg_get_libs (package, error) result(libraries) Get package libraries from pkg-config Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: package Package name type( error_t ), intent(out), allocatable :: error Error handler Return Value type( string_t ), allocatable, (:) A list of libraries public function pkgcfg_get_version (package, error) result(screen) Get package version from pkg-config Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: package Package name type( error_t ), intent(out), allocatable :: error Error handler Return Value type( string_t ) public function pkgcfg_has_package (name) result(success) Check if pkgcfg has package Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Package name Return Value logical public function pkgcfg_list_all (error, descriptions) result(modules) Return whole list of available pkg-cfg packages Read more… Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Error handler type( string_t ), intent(out), optional, allocatable :: descriptions (:) An optional list of package descriptions Return Value type( string_t ), allocatable, (:) A list of all available packages Subroutines public subroutine run_wrapper (wrapper, args, verbose, exitcode, cmd_success, screen_output) Simple call to execute_command_line involving one mpi* wrapper Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: wrapper type( string_t ), intent(in), optional :: args (:) logical, intent(in), optional :: verbose integer, intent(out), optional :: exitcode logical, intent(out), optional :: cmd_success type( string_t ), intent(out), optional :: screen_output","tags":"","loc":"module/fpm_pkg_config.html"},{"title":"fpm_manifest_preprocess – Fortran-lang/fpm","text":"Implementation of the meta data for preprocessing. A preprocess table can currently have the following fields [preprocess] [preprocess.cpp] suffixes = [ \"F90\" , \"f90\" ] directories = [ \"src/feature1\" , \"src/models\" ] macros = [] Uses fpm_error fpm_toml iso_fortran_env fpm_strings Derived Types type, public, extends( serializable_t ) :: preprocess_config_t Configuration meta data for a preprocessor Components Type Visibility Attributes Name Initial type( string_t ), public, allocatable :: directories (:) Directories to search for files to be preprocessed type( string_t ), public, allocatable :: macros (:) Macros to be defined for the preprocessor character(len=:), public, allocatable :: name Name of the preprocessor type( string_t ), public, allocatable :: suffixes (:) Suffixes of the files to be preprocessed Type-Bound Procedures procedure, public :: add_config procedure, public :: destroy ../../ Operations generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance procedure, public :: is_cpp ../../ Properties procedure, public :: is_fypp generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => preprocess_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_preprocess_config (self, table, error) Construct a new preprocess configuration from TOML data structure Arguments Type Intent Optional Attributes Name type( preprocess_config_t ), intent(out) :: self Instance of the preprocess configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure. type( error_t ), intent(out), allocatable :: error Error handling public subroutine new_preprocessors (preprocessors, table, error) Construct new preprocess array from a TOML data structure. Arguments Type Intent Optional Attributes Name type( preprocess_config_t ), intent(out), allocatable :: preprocessors (:) Instance of the preprocess configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_preprocess.html"},{"title":"fpm_model – Fortran-lang/fpm","text":"The fpm package model Defines the fpm model data types which encapsulate all information\n required to correctly build a package and its dependencies. The process (see [[build_model(subroutine)]] ) for generating a valid [[fpm_model]] involves\n source files discovery ( fpm_sources ) and parsing ( fpm_source_parsing ). Once a valid [[fpm_model]] has been constructed, it may be passed to [[fpm_targets:targets_from_sources]] to\n generate a list of build targets for the backend. Enumerations Source type: FPM_UNIT_* Describes the type of source file — determines build target generation The logical order of precedence for assigning unit_type is as follows: if source - file contains program then unit_type = FPM_UNIT_PROGRAM else if source - file contains non - module subroutine / function then unit_type = FPM_UNIT_SUBPROGRAM else if source - file contains submodule then unit_type = FPM_UNIT_SUBMODULE else if source - file contains module then unit_type = FPM_UNIT_MODULE end if @note Note\n A source file is only designated FPM_UNIT_MODULE if it only contains modules - no non-module subprograms.\n (This allows tree-shaking/pruning of build targets based on unused module dependencies.) Source scope: FPM_SCOPE_* Describes the scoping rules for using modules — controls module dependency resolution Uses iso_fortran_env fpm_toml fpm_dependency fpm_strings fpm_error fpm_compiler fpm_manifest_preprocess Variables Type Visibility Attributes Name Initial integer, public, parameter :: FPM_SCOPE_APP = 3 Module-use scope is library/dependency and app modules integer, public, parameter :: FPM_SCOPE_DEP = 2 Module-use scope is library/dependency modules only integer, public, parameter :: FPM_SCOPE_EXAMPLE = 5 integer, public, parameter :: FPM_SCOPE_LIB = 1 Module-use scope is library/dependency modules only integer, public, parameter :: FPM_SCOPE_TEST = 4 Module-use scope is library/dependency and test modules integer, public, parameter :: FPM_SCOPE_UNKNOWN = -1 Source has no module-use scope integer, public, parameter :: FPM_UNIT_CHEADER = 6 Source type is c header file integer, public, parameter :: FPM_UNIT_CPPSOURCE = 7 Souce type is c++ source file. integer, public, parameter :: FPM_UNIT_CSOURCE = 5 Source type is c source file integer, public, parameter :: FPM_UNIT_MODULE = 2 Source only contains one or more fortran modules integer, public, parameter :: FPM_UNIT_PROGRAM = 1 Source contains a fortran program integer, public, parameter :: FPM_UNIT_SUBMODULE = 3 Source contains one or more fortran submodules integer, public, parameter :: FPM_UNIT_SUBPROGRAM = 4 Source contains one or more fortran subprogram not within modules integer, public, parameter :: FPM_UNIT_UNKNOWN = -1 Source type unknown Derived Types type, public, extends( serializable_t ) :: fortran_features_t Enabled Fortran language features Components Type Visibility Attributes Name Initial logical, public :: implicit_external = .false. Use implicit external interface logical, public :: implicit_typing = .false. Use default implicit typing character(len=:), public, allocatable :: source_form Form to use for all Fortran sources Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => fft_dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => fft_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => fft_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: fpm_model_t Type describing everything required to build\n the root package and its dependencies. Components Type Visibility Attributes Name Initial type( archiver_t ), public :: archiver Archiver object character(len=:), public, allocatable :: build_prefix Base directory for build character(len=:), public, allocatable :: c_compile_flags Command line flags passed to C for compilation type( compiler_t ), public :: compiler Compiler object character(len=:), public, allocatable :: cxx_compile_flags Command line flags passed to C++ for compilation type( dependency_tree_t ), public :: deps Project dependencies logical, public :: enforce_module_names = .false. Whether module names should be prefixed with the package name type( string_t ), public, allocatable :: external_modules (:) External modules used character(len=:), public, allocatable :: fortran_compile_flags Command line flags passed to fortran for compilation type( string_t ), public, allocatable :: include_dirs (:) Include directories logical, public :: include_tests = .true. Whether tests should be added to the build list character(len=:), public, allocatable :: link_flags Command line flags passed to the linker type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public :: module_prefix Prefix for all module names character(len=:), public, allocatable :: package_name Name of root package type( package_t ), public, allocatable :: packages (:) Array of packages (including the root package) Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => model_dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => model_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => model_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: package_t Type for describing a single package Components Type Visibility Attributes Name Initial logical, public :: enforce_module_names = .false. Module naming conventions type( fortran_features_t ), public :: features Language features type( string_t ), public :: module_prefix Prefix for all module names character(len=:), public, allocatable :: name Name of package type( preprocess_config_t ), public :: preprocess List of macros. type( srcfile_t ), public, allocatable :: sources (:) Array of sources character(len=:), public, allocatable :: version Package version number. Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => package_dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => package_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => package_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: srcfile_t Type for describing a source file Components Type Visibility Attributes Name Initial integer(kind=int64), public :: digest Current hash character(len=:), public, allocatable :: exe_name Name of executable for FPM_UNIT_PROGRAM character(len=:), public, allocatable :: file_name File path relative to cwd type( string_t ), public, allocatable :: include_dependencies (:) Files INCLUDEd by this source file type( string_t ), public, allocatable :: link_libraries (:) Native libraries to link against type( string_t ), public, allocatable :: modules_provided (:) Modules provided by this source file (lowerstring) type( string_t ), public, allocatable :: modules_used (:) Modules USEd by this source file (lowerstring) type( string_t ), public, allocatable :: parent_modules (:) Parent modules (submodules only) integer, public :: unit_scope = FPM_SCOPE_UNKNOWN Target module-use scope integer, public :: unit_type = FPM_UNIT_UNKNOWN Type of source unit Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => srcfile_dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => srcfile_load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => srcfile_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Functions public function FPM_SCOPE_NAME (flag) result(name) Return the character name of a scope flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: flag Return Value character(len=:), allocatable public function FPM_UNIT_NAME (flag) result(name) Return the character name of a unit flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: flag Return Value character(len=:), allocatable Subroutines public subroutine show_model (model) Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(in) :: model","tags":"","loc":"module/fpm_model.html"},{"title":"fpm_backend_console – Fortran-lang/fpm","text":"Build Backend Console This module provides a lightweight implementation for printing to the console\n and updating previously-printed console lines. It used by [[fpm_backend_output]] for pretty-printing build status and progress. @note Note\n The implementation for updating previous lines relies on no other output\n going to stdout / stderr except through the console_t object provided. @note Note\n All write statements to stdout are enclosed within OpenMP critical regions Uses iso_fortran_env Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: COLOR_GREEN = ESC//\"[32m\" Escape code for green foreground color character(len=*), public, parameter :: COLOR_RED = ESC//\"[31m\" Escape code for red foreground color character(len=*), public, parameter :: COLOR_RESET = ESC//\"[0m\" Escape code to reset foreground color character(len=*), public, parameter :: COLOR_YELLOW = ESC//\"[93m\" Escape code for yellow foreground color character(len=*), public, parameter :: LINE_RESET = ESC//\"[2K\"//ESC//\"[1G\" Escape code for erasing current line Derived Types type, public :: console_t Console object Components Type Visibility Attributes Name Initial integer, public :: n_line = 1 Number of lines printed Type-Bound Procedures procedure, public :: update_line => console_update_line ../../ Update a previously-written console line procedure, public :: write_line => console_write_line ../../ Write a single line to the console","tags":"","loc":"module/fpm_backend_console.html"},{"title":"fpm_os – Fortran-lang/fpm","text":"Uses fpm_error fpm_environment iso_c_binding fpm_filesystem Subroutines public subroutine change_directory (path, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path type( error_t ), intent(out), allocatable :: error public subroutine convert_to_absolute_path (path, error) Converts a path to an absolute, canonical path. Arguments Type Intent Optional Attributes Name character(len=:), intent(inout), allocatable :: path type( error_t ), intent(out), allocatable :: error public subroutine get_absolute_path (path, absolute_path, error) Determine the canonical, absolute path for the given path.\nExpands home folder (~) on both Unix and Windows. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path character(len=:), intent(out), allocatable :: absolute_path type( error_t ), intent(out), allocatable :: error public subroutine get_absolute_path_by_cd (path, absolute_path, error) Alternative to get_absolute_path that uses chdir / _chdir to determine the absolute path. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path character(len=:), intent(out), allocatable :: absolute_path type( error_t ), intent(out), allocatable :: error public subroutine get_current_directory (path, error) Arguments Type Intent Optional Attributes Name character(len=:), intent(out), allocatable :: path type( error_t ), intent(out), allocatable :: error","tags":"","loc":"module/fpm_os.html"},{"title":"fpm_manifest_metapackages – Fortran-lang/fpm","text":"Implementation of the metapackage configuration data. A metapackage table can currently have the following fields [metapackages] fpm = \"0.1.0\" openmp = bool stdlib = bool Uses fpm_error fpm_toml fpm_environment Derived Types type, public :: metapackage_config_t Configuration data for metapackages Components Type Visibility Attributes Name Initial type( metapackage_request_t ), public :: hdf5 HDF5 type( metapackage_request_t ), public :: minpack fortran-lang minpack type( metapackage_request_t ), public :: mpi Request MPI support type( metapackage_request_t ), public :: openmp Request OpenMP support type( metapackage_request_t ), public :: stdlib Request stdlib support type, public :: metapackage_request_t Configuration data for a single metapackage request Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: name Metapackage name logical, public :: on = .false. Request flag character(len=:), public, allocatable :: version Version Specification string Functions public function is_meta_package (key) Check local schema for allowed entries Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: key Instance of the TOML data structure Return Value logical Subroutines public subroutine new_meta_config (self, table, meta_allowed, error) Construct a new build configuration from a TOML data structure Read more… Arguments Type Intent Optional Attributes Name type( metapackage_config_t ), intent(out) :: self Instance of the build configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure logical, intent(in) :: meta_allowed (:) List of keys allowed to be metapackages type( error_t ), intent(out), allocatable :: error Error handling public subroutine new_meta_request (self, key, table, meta_allowed, error) Construct a new metapackage request from the dependencies table Read more… Arguments Type Intent Optional Attributes Name type( metapackage_request_t ), intent(out) :: self character(len=*), intent(in) :: key The package name type(toml_table), intent(inout) :: table Instance of the TOML data structure logical, intent(in), optional :: meta_allowed (:) List of keys allowed to be metapackages type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_metapackages.html"},{"title":"fpm_cmd_publish – Fortran-lang/fpm","text":"Upload a package to the registry using the publish command. To upload a package you need to provide a token that will be linked to your username and created for a namespace.\nThe token can be obtained from the registry website. It can be used as fpm publish --token . Uses fpm_settings fpm fpm_command_line fpm_downloader fpm_manifest fpm_versioning fpm_model fpm_strings fpm_error fpm_git fpm_filesystem Subroutines public subroutine cmd_publish (settings) The publish command first builds the root package to obtain all the relevant information such as the\npackage version. It then creates a tarball of the package and uploads it to the registry.\nChecks before uploading the package. Arguments Type Intent Optional Attributes Name type( fpm_publish_settings ), intent(inout) :: settings","tags":"","loc":"module/fpm_cmd_publish.html"},{"title":"fpm_manifest_example – Fortran-lang/fpm","text":"Implementation of the meta data for an example. The example data structure is effectively a decorated version of an executable\n and shares most of its properties, except for the defaults and can be\n handled under most circumstances just like any other executable. A example table can currently have the following fields [[ example ]] name = \"string\" source-dir = \"path\" main = \"file\" link = [ \"lib\" ] [example.dependencies] Uses fpm_error fpm_toml fpm_manifest_dependency fpm_manifest_executable Derived Types type, public, extends( executable_config_t ) :: example_config_t Configuation meta data for an example Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => exe_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_example (self, table, error) Construct a new example configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( example_config_t ), intent(out) :: self Instance of the example configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_example.html"},{"title":"fpm_source_parsing – Fortran-lang/fpm","text":"Parsing of package source files This module exposes two functions, [[parse_f_source]] and [[parse_c_source]] ,\n which perform a rudimentary parsing of fortran and c source files\n in order to extract information required for module dependency tracking. Both functions additionally calculate and store a file digest (hash) which\n is used by the backend ( fpm_backend ) to skip compilation of unmodified sources. Both functions return an instance of the srcfile_t type. For more information, please read the documentation for each function: [[parse_f_source]] [[parse_c_source]] Uses fpm_error fpm_filesystem fpm_model fpm_strings Functions public function parse_c_source (c_filename, error) result(c_source) Parsing of c, cpp source files Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: c_filename type( error_t ), intent(out), allocatable :: error Return Value type( srcfile_t ) public function parse_f_source (f_filename, error) result(f_source) Parsing of free-form fortran source files Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_filename type( error_t ), intent(out), allocatable :: error Return Value type( srcfile_t ) Subroutines public subroutine parse_use_statement (f_filename, i, line, use_stmt, is_intrinsic, module_name, error) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_filename Current file name and line number (for error messaging) integer, intent(in) :: i character(len=*), intent(in) :: line The line being parsed. MUST BE preprocessed with trim(adjustl() logical, intent(out) :: use_stmt Does this line contain a use statement? logical, intent(out) :: is_intrinsic Is the module in this statement intrinsic? character(len=:), intent(out), allocatable :: module_name used module name type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_source_parsing.html"},{"title":"fpm_manifest_executable – Fortran-lang/fpm","text":"Implementation of the meta data for an executables. An executable table can currently have the following fields [[ executable ]] name = \"string\" source-dir = \"path\" main = \"file\" link = [ \"lib\" ] [executable.dependencies] Uses fpm_error fpm_toml fpm_manifest_dependency fpm_strings Derived Types type, public, extends( serializable_t ) :: executable_config_t Configuation meta data for an executable Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => exe_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_executable (self, table, error) Construct a new executable configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( executable_config_t ), intent(out) :: self Instance of the executable configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_executable.html"},{"title":"fpm_cmd_new – Fortran-lang/fpm","text":"Definition of the “new” subcommand A type of the general command base class fpm_cmd_settings was created for the “new” subcommand ==> type fpm_new_settings .\n This procedure read the values that were set on the command line\n from this type to decide what actions to take. It is virtually self-contained and so independant of the rest of the\n application that it could function as a separate program. The “new” subcommand options currently consist of a SINGLE top\n directory name to create that must have a name that is an\n allowable Fortran variable name. That should have been ensured\n by the command line processing before this procedure is called.\n So basically this routine has already had the options vetted and\n just needs to conditionally create a few files. As described in the documentation it will selectively\n create the subdirectories app/, test/, src/, and example/\n and populate them with sample files. It also needs to create an initial manifest file “fpm.toml”. It then calls the system command “git init”. It should test for file existence and not overwrite existing\n files and inform the user if there were conflicts. Any changes should be reflected in the documentation in fpm_command_line.f90 FUTURE\n A filename like “.” would need system commands or a standard routine\n like realpath(3c) to process properly. Perhaps allow more than one name on a single command. It is an arbitrary\n restriction based on a concensus preference, not a required limitation. Initially the name of the directory is used as the module name in the\n src file so it must be an allowable Fortran variable name. If there are\n complaints about it it might be changed. Handling unicode at this point\n might be problematic as not all current compilers handle it. Other\n utilities like content trackers (ie. git) or repositories like github\n might also have issues with alternative names or names with spaces, etc.\n So for the time being it seems prudent to encourage simple ASCII top directory\n names (similiar to the primary programming language Fortran itself). Should be able to create or pull more complicated initial examples\n based on various templates. It should place or mention other relevant\n documents such as a description of the manifest file format in user hands;\n or how to access registered packages and local packages,\n although some other command might provide that (and the help command should\n be the first go-to for a CLI utility). Uses fpm_environment iso_fortran_env fpm_command_line fpm_strings fpm_error fpm_filesystem Subroutines public subroutine cmd_new (settings) TOP DIRECTORY NAME PROCESSING\nsee if requested new directory already exists and process appropriately\ntemporarily change to new directory as a test. NB: System dependent Arguments Type Intent Optional Attributes Name type( fpm_new_settings ), intent(in) :: settings","tags":"","loc":"module/fpm_cmd_new.html"},{"title":"fpm_settings – Fortran-lang/fpm","text":"Manages global settings which are defined in the global config file. Uses fpm_toml fpm_os fpm_environment fpm_error fpm_filesystem Variables Type Visibility Attributes Name Initial character(len=*), public, parameter :: official_registry_base_url = 'https://fpm-registry.vercel.app' Derived Types type, public :: fpm_global_settings Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: config_file_name Name of the global config file. The default is config.toml . character(len=:), public, allocatable :: path_to_config_folder Path to the global config file excluding the file name. type(fpm_registry_settings), public, allocatable :: registry_settings Registry configs. Type-Bound Procedures procedure, public :: full_path procedure, public :: has_custom_location procedure, public :: path_to_config_folder_or_empty Subroutines public subroutine get_global_settings (global_settings, error) Obtain global settings from the global config file. Arguments Type Intent Optional Attributes Name type( fpm_global_settings ), intent(inout) :: global_settings Global settings to be obtained. type( error_t ), intent(out), allocatable :: error Error reading config file. public subroutine get_registry_settings (table, global_settings, error) Read registry settings from the global config file. Arguments Type Intent Optional Attributes Name type(toml_table), intent(inout), target :: table The [registry] subtable from the global config file. type( fpm_global_settings ), intent(inout) :: global_settings The global settings which can be filled with the registry settings. type( error_t ), intent(out), allocatable :: error Error handling.","tags":"","loc":"module/fpm_settings.html"},{"title":"fpm_manifest_library – Fortran-lang/fpm","text":"Implementation of the meta data for libraries. A library table can currently have the following fields [library] source-dir = \"path\" include-dir = [ \"path1\" , \"path2\" ] build-script = \"file\" Uses fpm_error fpm_toml fpm_strings Derived Types type, public, extends( serializable_t ) :: library_config_t Configuration meta data for a library Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: build_script Alternative build script to be invoked type( string_t ), public, allocatable :: include_dir (:) Include path prefix character(len=:), public, allocatable :: source_dir Source path prefix Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => library_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_library (self, table, error) Construct a new library configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( library_config_t ), intent(out) :: self Instance of the library configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_library.html"},{"title":"fpm_compiler – Fortran-lang/fpm","text":"Define compiler command options This module defines compiler options to use for the debug and release builds. Uses iso_fortran_env fpm_environment fpm_toml fpm_manifest fpm_strings fpm_error fpm_filesystem Variables Type Visibility Attributes Name Initial integer, public, parameter :: compiler_enum = kind(id_unknown) character(len=*), public, parameter :: flag_cray_fixed_form = \" -ffixed\" character(len=*), public, parameter :: flag_cray_free_form = \" -ffree\" character(len=*), public, parameter :: flag_cray_implicit_typing = \" -el\" character(len=*), public, parameter :: flag_cray_no_implicit_typing = \" -dl\" character(len=*), public, parameter :: flag_gnu_backtrace = \" -fbacktrace\" character(len=*), public, parameter :: flag_gnu_check = \" -fcheck=bounds -fcheck=array-temps\" character(len=*), public, parameter :: flag_gnu_coarray = \" -fcoarray=single\" character(len=*), public, parameter :: flag_gnu_debug = \" -g\" character(len=*), public, parameter :: flag_gnu_external = \" -Wimplicit-interface\" character(len=*), public, parameter :: flag_gnu_fixed_form = \" -ffixed-form\" character(len=*), public, parameter :: flag_gnu_free_form = \" -ffree-form\" character(len=*), public, parameter :: flag_gnu_limit = \" -fmax-errors=1\" character(len=*), public, parameter :: flag_gnu_no_implicit_external = \" -Werror=implicit-interface\" character(len=*), public, parameter :: flag_gnu_no_implicit_typing = \" -fimplicit-none\" character(len=*), public, parameter :: flag_gnu_openmp = \" -fopenmp\" character(len=*), public, parameter :: flag_gnu_opt = \" -O3 -funroll-loops\" character(len=*), public, parameter :: flag_gnu_pic = \" -fPIC\" character(len=*), public, parameter :: flag_gnu_warn = \" -Wall -Wextra\" character(len=*), public, parameter :: flag_ibmxl_backslash = \" -qnoescape\" character(len=*), public, parameter :: flag_intel_align = \" -align all\" character(len=*), public, parameter :: flag_intel_align_win = \" /align:all\" character(len=*), public, parameter :: flag_intel_backtrace = \" -traceback\" character(len=*), public, parameter :: flag_intel_backtrace_win = \" /traceback\" character(len=*), public, parameter :: flag_intel_byterecl = \" -assume byterecl\" character(len=*), public, parameter :: flag_intel_byterecl_win = \" /assume:byterecl\" character(len=*), public, parameter :: flag_intel_check = \" -check all\" character(len=*), public, parameter :: flag_intel_check_win = \" /check:all\" character(len=*), public, parameter :: flag_intel_debug = \" -O0 -g\" character(len=*), public, parameter :: flag_intel_debug_win = \" /Od /Z7\" character(len=*), public, parameter :: flag_intel_fixed_form = \" -fixed\" character(len=*), public, parameter :: flag_intel_fixed_form_win = \" /fixed\" character(len=*), public, parameter :: flag_intel_fp = \" -fp-model precise -pc64\" character(len=*), public, parameter :: flag_intel_fp_win = \" /fp:precise\" character(len=*), public, parameter :: flag_intel_free_form = \" -free\" character(len=*), public, parameter :: flag_intel_free_form_win = \" /free\" character(len=*), public, parameter :: flag_intel_limit = \" -error-limit 1\" character(len=*), public, parameter :: flag_intel_limit_win = \" /error-limit:1\" character(len=*), public, parameter :: flag_intel_llvm_check = \" -check all,nouninit\" character(len=*), public, parameter :: flag_intel_nogen = \" -nogen-interfaces\" character(len=*), public, parameter :: flag_intel_nogen_win = \" /nogen-interfaces\" character(len=*), public, parameter :: flag_intel_openmp = \" -qopenmp\" character(len=*), public, parameter :: flag_intel_openmp_win = \" /Qopenmp\" character(len=*), public, parameter :: flag_intel_opt = \" -O3\" character(len=*), public, parameter :: flag_intel_opt_win = \" /O3\" character(len=*), public, parameter :: flag_intel_pthread = \" -reentrancy threaded\" character(len=*), public, parameter :: flag_intel_pthread_win = \" /reentrancy:threaded\" character(len=*), public, parameter :: flag_intel_standard_compliance = \" -standard-semantics\" character(len=*), public, parameter :: flag_intel_standard_compliance_win = \" /standard-semantics\" character(len=*), public, parameter :: flag_intel_warn = \" -warn all\" character(len=*), public, parameter :: flag_intel_warn_win = \" /warn:all\" character(len=*), public, parameter :: flag_lfortran_fixed_form = \" --fixed-form\" character(len=*), public, parameter :: flag_lfortran_implicit_external = \" --implicit-interface\" character(len=*), public, parameter :: flag_lfortran_implicit_typing = \" --implicit-typing\" character(len=*), public, parameter :: flag_lfortran_openmp = \" --openmp\" character(len=*), public, parameter :: flag_lfortran_opt = \" --fast\" character(len=*), public, parameter :: flag_nag_backtrace = \" -gline\" character(len=*), public, parameter :: flag_nag_check = \" -C\" character(len=*), public, parameter :: flag_nag_coarray = \" -coarray=single\" character(len=*), public, parameter :: flag_nag_debug = \" -g -O0\" character(len=*), public, parameter :: flag_nag_fixed_form = \" -fixed\" character(len=*), public, parameter :: flag_nag_free_form = \" -free\" character(len=*), public, parameter :: flag_nag_no_implicit_typing = \" -u\" character(len=*), public, parameter :: flag_nag_openmp = \" -openmp\" character(len=*), public, parameter :: flag_nag_opt = \" -O4\" character(len=*), public, parameter :: flag_nag_pic = \" -PIC\" character(len=*), public, parameter :: flag_pgi_backslash = \" -Mbackslash\" character(len=*), public, parameter :: flag_pgi_check = \" -Mbounds -Mchkptr -Mchkstk\" character(len=*), public, parameter :: flag_pgi_debug = \" -g\" character(len=*), public, parameter :: flag_pgi_fixed_form = \" -Mfixed\" character(len=*), public, parameter :: flag_pgi_free_form = \" -Mfree\" character(len=*), public, parameter :: flag_pgi_openmp = \" -mp\" character(len=*), public, parameter :: flag_pgi_traceback = \" -traceback\" character(len=*), public, parameter :: flag_pgi_warn = \" -Minform=inform\" Enumerations enum, bind(c) Enumerators enumerator :: id_unknown = 0 enumerator :: id_gcc = 1 enumerator :: id_f95 = 2 enumerator :: id_caf = 3 enumerator :: id_intel_classic_nix = 4 enumerator :: id_intel_classic_mac = 5 enumerator :: id_intel_classic_windows = 6 enumerator :: id_intel_llvm_nix = 7 enumerator :: id_intel_llvm_windows = 8 enumerator :: id_intel_llvm_unknown = 9 enumerator :: id_pgi = 10 enumerator :: id_nvhpc = 11 enumerator :: id_nag = 12 enumerator :: id_flang = 13 enumerator :: id_flang_new = 14 enumerator :: id_f18 = 15 enumerator :: id_ibmxl = 16 enumerator :: id_cray = 17 enumerator :: id_lahey = 18 enumerator :: id_lfortran = 19 Interfaces public interface debug Create debug printout public pure function debug_compiler (self) result(repr) String representation of a compiler object Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string public pure function debug_archiver (self) result(repr) String representation of an archiver object Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(in) :: self Instance of the archiver object Return Value character(len=:), allocatable Representation as string Derived Types type, public, extends( serializable_t ) :: archiver_t Definition of archiver object Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: ar Path to archiver logical, public :: echo = .true. Print all command logical, public :: use_response_file = .false. Use response files to pass arguments logical, public :: verbose = .true. Verbose output of command Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml procedure, public :: make_archive ../../ Create static archive generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => ar_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip type, public, extends( serializable_t ) :: compiler_t Definition of compiler object Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: cc Path to the C compiler character(len=:), public, allocatable :: cxx Path to the C++ compiler logical, public :: echo = .true. Print all commands character(len=:), public, allocatable :: fc Path to the Fortran compiler integer(kind=compiler_enum), public :: id = id_unknown Identifier of the compiler logical, public :: verbose = .true. Verbose output of command Type-Bound Procedures procedure, public :: check_fortran_source_runs ../../ Fortran feature support procedure, public :: compile_c ../../ Compile a C object procedure, public :: compile_cpp ../../ Compile a CPP object procedure, public :: compile_fortran ../../ Compile a Fortran object generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml => compiler_dump procedure, public :: enumerate_libraries ../../ Enumerate libraries, based on compiler and platform procedure, public :: get_default_flags ../../ Get default compiler flags procedure, public :: get_feature_flag ../../ Get feature flag procedure, public :: get_include_flag ../../ Get flag for include directories procedure, public :: get_main_flags ../../ Get flags for the main linking command procedure, public :: get_module_flag ../../ Get flag for module output directories procedure, public :: is_gnu ../../ Check whether this is a GNU compiler procedure, public :: is_intel ../../ Check whether this is an Intel compiler procedure, public :: is_unknown ../../ Check whether compiler is recognized procedure, public :: link ../../ Link executable generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml => compiler_load procedure, public :: name => compiler_name ../../ Return compiler name generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => compiler_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip procedure, public :: with_qp procedure, public :: with_xdp Functions public function ar_is_same (this, that) Check that two archiver_t objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical public function check_compiler (compiler, expected) result(match) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler character(len=*), intent(in) :: expected Return Value logical public function check_fortran_source_runs (self, input) result(success) Run a single-source Fortran program using the current compiler\nCompile a Fortran object\nCreate temporary source file\nWrite contents\nCompile and link program\nRun and retrieve exit code Read more… Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Program Source Return Value logical public function compiler_is_same (this, that) Check that two compiler_t objects are equal\nAll checks passed! Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: this class( serializable_t ), intent(in) :: that Return Value logical public pure function compiler_name (self) result(name) Return a compiler name string Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string public pure function debug_archiver (self) result(repr) String representation of an archiver object Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(in) :: self Instance of the archiver object Return Value character(len=:), allocatable Representation as string public pure function debug_compiler (self) result(repr) String representation of a compiler object Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(in) :: self Instance of the compiler object Return Value character(len=:), allocatable Representation as string public function enumerate_libraries (self, prefix, libs) result(r) Enumerate libraries, based on compiler and platform Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: prefix type( string_t ), intent(in) :: libs (:) Return Value character(len=:), allocatable public function get_compiler_id (compiler) result(id) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler Return Value integer(kind=compiler_enum) public function get_default_flags (self, release) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self logical, intent(in) :: release Return Value character(len=:), allocatable public function get_feature_flag (self, feature) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: feature Return Value character(len=:), allocatable public function get_id (compiler) result(id) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: compiler Return Value integer(kind=compiler_enum) public function get_include_flag (self, path) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function get_macros (id, macros_list, version) result(macros) This function will parse and read the macros list and\nreturn them as defined flags.\nSet macro defintion symbol on the basis of compiler used\nCheck if macros are not allocated.\nSplit the macro name and value. Read more… Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id type( string_t ), intent(in), allocatable :: macros_list (:) character(len=:), intent(in), allocatable :: version Return Value character(len=:), allocatable public function get_module_flag (self, path) result(flags) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: path Return Value character(len=:), allocatable public pure function is_gnu (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical public pure function is_intel (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical public pure function is_unknown (self) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Return Value logical public function with_qp (self) Check if the current compiler supports 128-bit real precision Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical public function with_xdp (self) Check if the current compiler supports 80-bit “extended” real precision Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object Return Value logical Subroutines public subroutine compile_c (self, input, output, args, log_file, stat) Compile a C object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine compile_cpp (self, input, output, args, log_file, stat) Compile a CPP object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine compile_fortran (self, input, output, args, log_file, stat) Compile a Fortran object Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: input Source file input character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine compiler_dump (self, table, error) Dump dependency to toml table Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine compiler_load (self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine dump_to_toml (self, table, error) Dump dependency to toml table Read more… Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine get_debug_compile_flags (id, flags) Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(out), allocatable :: flags public subroutine get_default_c_compiler (f_compiler, c_compiler) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_compiler character(len=:), intent(out), allocatable :: c_compiler public subroutine get_default_cxx_compiler (f_compiler, cxx_compiler) Get C++ Compiler. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: f_compiler character(len=:), intent(out), allocatable :: cxx_compiler public subroutine get_main_flags (self, language, flags) Get special flags for the main linker Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self character(len=*), intent(in) :: language character(len=:), intent(out), allocatable :: flags public subroutine get_release_compile_flags (id, flags) Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(out), allocatable :: flags public subroutine link (self, output, args, log_file, stat) Link an executable Arguments Type Intent Optional Attributes Name class( compiler_t ), intent(in) :: self Instance of the compiler object character(len=*), intent(in) :: output Output file of object character(len=*), intent(in) :: args Arguments for compiler character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine load_from_toml (self, table, error) Read dependency from toml table (no checks made at this stage) Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(inout) :: self Instance of the serializable object type(toml_table), intent(inout) :: table Data structure type( error_t ), intent(out), allocatable :: error Error handling public subroutine make_archive (self, output, args, log_file, stat) Create an archive Read more… Arguments Type Intent Optional Attributes Name class( archiver_t ), intent(in) :: self Instance of the archiver object character(len=*), intent(in) :: output Name of the archive to generate type( string_t ), intent(in) :: args (:) Object files to include into the archive character(len=*), intent(in) :: log_file Compiler output log file integer, intent(out) :: stat Status flag public subroutine new_archiver (self, ar, echo, verbose) Create new archiver instance Arguments Type Intent Optional Attributes Name type( archiver_t ), intent(out) :: self New instance of the archiver character(len=*), intent(in) :: ar User provided archiver command logical, intent(in) :: echo Echo compiler command logical, intent(in) :: verbose Verbose mode: dump compiler output public subroutine new_compiler (self, fc, cc, cxx, echo, verbose) Create new compiler instance Arguments Type Intent Optional Attributes Name type( compiler_t ), intent(out) :: self New instance of the compiler character(len=*), intent(in) :: fc Fortran compiler name or path character(len=*), intent(in) :: cc C compiler name or path character(len=*), intent(in) :: cxx C++ Compiler name or path logical, intent(in) :: echo Echo compiler command logical, intent(in) :: verbose Verbose mode: dump compiler output public pure subroutine set_cpp_preprocessor_flags (id, flags) Modify the flag_cpp_preprocessor on the basis of the compiler. Arguments Type Intent Optional Attributes Name integer(kind=compiler_enum), intent(in) :: id character(len=:), intent(inout), allocatable :: flags public subroutine write_response_file (name, argv) Response files allow to read command line options from files.\nWhitespace is used to separate the arguments, we will use newlines\nas separator to create readable response files which can be inspected\nin case of errors. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name type( string_t ), intent(in) :: argv (:)","tags":"","loc":"module/fpm_compiler.html"},{"title":"fpm_error – Fortran-lang/fpm","text":"Implementation of basic error handling. Uses iso_fortran_env fpm_strings Derived Types type, public :: error_t Data type defining an error Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: message Error message Functions public function bad_name_error (error, label, name) Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: label Error message label to add to message character(len=*), intent(in) :: name name value to check Return Value logical Subroutines public subroutine fatal_error (error, message) Generic fatal runtime error Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: message Error message public subroutine file_not_found_error (error, file_name) Error created when a file is missing or not found Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: file_name Name of the missing file public subroutine file_parse_error (error, file_name, message, line_num, line_string, line_col) Error created when file parsing fails Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: file_name Name of file character(len=*), intent(in) :: message Parse error message integer, intent(in), optional :: line_num Line number of parse error character(len=*), intent(in), optional :: line_string Line context string integer, intent(in), optional :: line_col Line context column public subroutine fpm_stop (value, message) Arguments Type Intent Optional Attributes Name integer, intent(in) :: value value to use on STOP character(len=*), intent(in) :: message Error message public subroutine syntax_error (error, message) Arguments Type Intent Optional Attributes Name type( error_t ), intent(out), allocatable :: error Instance of the error data character(len=*), intent(in) :: message Error message","tags":"","loc":"module/fpm_error.html"},{"title":"fpm_release – Fortran-lang/fpm","text":"Release parameters Module fpm_release contains public constants storing this build’s unique version IDs Uses fpm_error fpm_versioning Functions public function fpm_version () Return the current fpm version from fpm_version_ID as a version type Arguments None Return Value type( version_t )","tags":"","loc":"module/fpm_release.html"},{"title":"fpm_manifest_test – Fortran-lang/fpm","text":"Implementation of the meta data for a test. The test data structure is effectively a decorated version of an executable\n and shares most of its properties, except for the defaults and can be\n handled under most circumstances just like any other executable. A test table can currently have the following fields [[ test ]] name = \"string\" source-dir = \"path\" main = \"file\" link = [ \"lib\" ] [test.dependencies] Uses fpm_error fpm_toml fpm_manifest_dependency fpm_manifest_executable Derived Types type, public, extends( executable_config_t ) :: test_config_t Configuation meta data for an test Components Type Visibility Attributes Name Initial type( dependency_config_t ), public, allocatable :: dependency (:) Dependency meta data for this executable type( string_t ), public, allocatable :: link (:) Libraries to link against character(len=:), public, allocatable :: main Name of the source file declaring the main program character(len=:), public, allocatable :: name Name of the resulting executable character(len=:), public, allocatable :: source_dir Source directory for collecting the executable Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml procedure, public :: info ../../ Print information on this instance generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => exe_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_test (self, table, error) Construct a new test configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( test_config_t ), intent(out) :: self Instance of the test configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_test.html"},{"title":"fpm_meta – Fortran-lang/fpm","text":"The fpm meta-package model This is a wrapper data type that encapsulate all pre-processing information\n (compiler flags, linker libraries, etc.) required to correctly enable a package\n to use a core library. Available core libraries OpenMP MPI HDF5 fortran-lang stdlib fortran-lang minpack @note Note\n Core libraries are enabled in the [build] section of the fpm.toml manifest Uses fpm_environment iso_fortran_env regex_module shlex_module fpm_manifest_dependency fpm_command_line fpm_os fpm_pkg_config fpm_manifest fpm_versioning fpm_model fpm_strings fpm_error fpm_compiler fpm_git fpm_filesystem Interfaces public interface resolve_metapackages private subroutine resolve_metapackage_model(model, package, settings, error) Resolve all metapackages into the package config Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(inout) :: model type( package_config_t ), intent(inout) :: package class( fpm_build_settings ), intent(inout) :: settings type( error_t ), intent(out), allocatable :: error Derived Types type, public :: metapackage_t Type for describing a source file Components Type Visibility Attributes Name Initial type( string_t ), public :: cflags type( string_t ), public :: cxxflags type( dependency_config_t ), public, allocatable :: dependency (:) List of Development dependency meta data.\nMetapackage dependencies are never exported from the model type( string_t ), public, allocatable :: external_modules (:) type( string_t ), public :: fflags type( string_t ), public :: flags List of compiler flags and options to be added type( fortran_features_t ), public, allocatable :: fortran Special fortran features logical, public :: has_build_flags = .false. logical, public :: has_c_flags = .false. logical, public :: has_cxx_flags = .false. logical, public :: has_dependencies = .false. logical, public :: has_external_modules = .false. logical, public :: has_fortran_flags = .false. logical, public :: has_include_dirs = .false. logical, public :: has_link_flags = .false. logical, public :: has_link_libraries = .false. logical, public :: has_run_command = .false. type( string_t ), public, allocatable :: incl_dirs (:) type( string_t ), public :: link_flags type( string_t ), public, allocatable :: link_libs (:) type( string_t ), public :: run_command type( version_t ), public, allocatable :: version Package version (if supported) Type-Bound Procedures procedure, public :: destroy ../../ Clean metapackage structure procedure, public :: new => init_from_name ../../ Initialize the metapackage structure from its given name generic, public :: resolve => resolve_cmd, resolve_model, resolve_package_config Functions public pure function MPI_TYPE_NAME (mpilib) result(name) Return a name for the MPI library Arguments Type Intent Optional Attributes Name integer, intent(in) :: mpilib Return Value character(len=:), allocatable","tags":"","loc":"module/fpm_meta.html"},{"title":"fpm_strings – Fortran-lang/fpm","text":"This module defines general procedures for string operations for both CHARACTER and\n TYPE(STRING_T) variables general routines for performing string operations Types TYPE(STRING_T) define a type to contain strings of variable length Type Conversions f_string return Fortran CHARACTER variable when given a C-like array of\n single characters terminated with a C_NULL_CHAR CHARACTER str Converts INTEGER or LOGICAL to CHARACTER string Case lower Changes a string to lowercase over optional specified column range Parsing and joining split parse string on delimiter characters and store tokens into an allocatable array split_first_last Computes the first and last indices of tokens in input string, delimited by the characters in set,\n and stores them into first and last output arrays. string_cat Concatenate an array of type(string_t) into a single CHARACTER variable join append an array of CHARACTER variables into a single CHARACTER variable Testing str_ends_with test if a CHARACTER string or array ends with a specified suffix string_array_contains Check if array of TYPE(STRING_T) matches a particular CHARACTER string OPERATOR(.IN.) Check if array of TYPE(STRING_T) matches a particular CHARACTER string glob function compares text strings, one of which can have wildcards (‘*’ or ‘?’). is_fortran_name determine whether a string is an acceptable Fortran entity name to_fortran_name replace allowed special but unusuable characters in names with underscore Whitespace notabs subroutine to expand tab characters assuming a tab space every eight characters dilate function to expand tab characters assuming a tab space every eight characters len_trim Determine total trimmed length of STRING_T array Miscellaneous fnv_1a Hash a CHARACTER(*) string of default kind or a TYPE(STRING_T) array replace Returns string with characters in charset replaced with target_char. resize increase the size of a TYPE(STRING_T) array by N elements Module naming License: Public Domain\n Changes a string to upprtcase over optional specified column range\n Author: Milan Curcic\n Computes the first and last indices of tokens in input string, delimited\n by the characters in set, and stores them into first and last output\n arrays.\n Author: Milan Curcic\n If back is absent, computes the leftmost token delimiter in string whose\n position is > pos. If back is present and true, computes the rightmost\n token delimiter in string whose position is < pos. The result is stored\n in pos. Uses iso_fortran_env iso_c_binding Interfaces public interface fnv_1a private pure function fnv_1a_char(input, seed) result(hash) Hash a character(*) string of default kind Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: input integer(kind=int64), intent(in), optional :: seed Return Value integer(kind=int64) private pure function fnv_1a_string_t(input, seed) result(hash) Hash a string_t array of default kind Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: input (:) integer(kind=int64), intent(in), optional :: seed Return Value integer(kind=int64) public interface len_trim private elemental function string_len_trim(string) result(n) Determine total trimmed length of string_t array Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: string Return Value integer private pure function strings_len_trim(strings) result(n) Determine total trimmed length of string_t array Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: strings (:) Return Value integer public interface operator(.in.) public function string_array_contains (search_string, array) Check if array of TYPE(STRING_T) matches a particular CHARACTER string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: search_string type( string_t ), intent(in) :: array (:) Return Value logical public interface operator(==) private pure function string_is_same(this, that) Check that two string objects are exactly identical Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: this two strings to be compared type( string_t ), intent(in) :: that two strings to be compared Return Value logical private pure function string_arrays_same(this, that) Check that two allocatable string object arrays are exactly identical Arguments Type Intent Optional Attributes Name type( string_t ), intent(in), allocatable :: this (:) two string arrays to be compared type( string_t ), intent(in), allocatable :: that (:) two string arrays to be compared Return Value logical public interface resize private subroutine resize_string(list, n) increase the size of a TYPE(STRING_T) array by N elements Arguments Type Intent Optional Attributes Name type( string_t ), intent(inout), allocatable :: list (:) Instance of the array to be resized integer, intent(in), optional :: n Dimension of the final array size public interface str private pure function str_int(i) result(s) Converts integer “i” to string Arguments Type Intent Optional Attributes Name integer, intent(in) :: i Return Value character(len=str_int_len) private pure function str_int64(i) result(s) Converts integer “i” to string Arguments Type Intent Optional Attributes Name integer(kind=int64), intent(in) :: i Return Value character(len=str_int64_len) private pure function str_logical(l) result(s) Converts logical “l” to string Arguments Type Intent Optional Attributes Name logical, intent(in) :: l Return Value character(len=str_logical_len) public interface str_ends_with private pure function str_ends_with_str(s, e) result(r) test if a CHARACTER string ends with a specified suffix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e Return Value logical private pure function str_ends_with_any(s, e) result(r) test if a CHARACTER string ends with any of an array of suffixs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e (:) Return Value logical private pure function str_ends_with_any_string(s, e) result(r) Test if a CHARACTER string ends with any of an array of string suffixs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s type( string_t ), intent(in) :: e (:) Return Value logical public interface string_t private function new_string_t(s) result(string) Helper function to generate a new string_t instance\n (Required due to the allocatable component) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s Return Value type( string_t ) Derived Types type, public :: string_t Components Type Visibility Attributes Name Initial character(len=:), public, allocatable :: s Constructor private\n\n \n function new_string_t (s) Helper function to generate a new string_t instance\n (Required due to the allocatable component) Functions public function dilate (instr) result(outstr) Author John S. Urban License Public Domain Sample program: Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: instr Return Value character(len=:), allocatable public function f_string (c_string) return Fortran character variable when given a C-like array of\nsingle characters terminated with a C_NULL_CHAR character Arguments Type Intent Optional Attributes Name character(len=1), intent(in) :: c_string (:) Return Value character(len=:), allocatable public function glob (tame, wild) Author John S. Urban License Public Domain glob(3f) compares given STRING for match to PATTERN which may\n contain wildcard characters. Read more… Arguments Type Intent Optional Attributes Name character(len=*) :: tame A string without wildcards to compare to the globbing expression character(len=*) :: wild A (potentially) corresponding string with wildcards Return Value logical result of test public function has_valid_custom_prefix (module_name, custom_prefix) result(valid) Check that a module name is prefixed with a custom prefix:\n1) It must be a valid FORTRAN name subset (<=63 chars, begin with letter, only alphanumeric allowed)\n2) It must begin with the prefix\n3) If longer, package name must be followed by default separator (“_”) plus at least one char Read more… Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: custom_prefix Return Value logical public function has_valid_standard_prefix (module_name, package_name) result(valid) Check that a module name is prefixed with the default package prefix:\n1) It must be a valid FORTRAN name (<=63 chars, begin with letter, “_” is only allowed non-alphanumeric)\n2) It must begin with the package name\n3) If longer, package name must be followed by default separator plus at least one char Read more… Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: package_name Return Value logical public elemental function is_fortran_name (line) result(lout) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: line Return Value logical public function is_valid_module_name (module_name, package_name, custom_prefix, enforce_module_names) result(valid) Check that a module name fits the current naming rules:\n1) It must be a valid FORTRAN name (<=63 chars, begin with letter, “_” is only allowed non-alphanumeric)\n2) It must begin with the package name\n3) If longer, package name must be followed by default separator plus at least one char Read more… Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_name type( string_t ), intent(in) :: package_name type( string_t ), intent(in) :: custom_prefix logical, intent(in) :: enforce_module_names Return Value logical public function is_valid_module_prefix (module_prefix) result(valid) Check that a custom module prefix fits the current naming rules:\n1) Only alphanumeric characters (no spaces, dashes, underscores or other characters)\n2) Does not begin with a number (Fortran-compatible syntax) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: module_prefix Return Value logical public pure function join (str, sep, trm, left, right, start, end) result(string) Author John S. Urban License Public Domain JOIN(3f) appends the elements of a CHARACTER array into a single\n CHARACTER variable, with elements 1 to N joined from left to right.\n By default each element is trimmed of trailing spaces and the\n default separator is a null string. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str (:) character(len=*), intent(in), optional :: sep logical, intent(in), optional :: trm character(len=*), intent(in), optional :: left character(len=*), intent(in), optional :: right character(len=*), intent(in), optional :: start character(len=*), intent(in), optional :: end Return Value character(len=:), allocatable public pure elemental function lower (str, begin, end) result(string) Author John S. Urban License Public Domain Changes a string to lowercase over optional specified column range Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str integer, intent(in), optional :: begin integer, intent(in), optional :: end Return Value character(len=len(str)) public function module_prefix_template (project_name, custom_prefix) result(prefix) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: project_name type( string_t ), intent(in) :: custom_prefix Return Value type( string_t ) public function module_prefix_type (project_name, custom_prefix) result(ptype) Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: project_name type( string_t ), intent(in) :: custom_prefix Return Value type( string_t ) public pure function replace (string, charset, target_char) result(res) Returns string with characters in charset replaced with target_char. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string character(len=1), intent(in) :: charset (:) character(len=1), intent(in) :: target_char Return Value character(len=len(string)) public pure function str_begins_with_str (s, e, case_sensitive) result(r) test if a CHARACTER string begins with a specified prefix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: s character(len=*), intent(in) :: e logical, intent(in), optional :: case_sensitive Return Value logical public function string_array_contains (search_string, array) Check if array of TYPE(STRING_T) matches a particular CHARACTER string Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: search_string type( string_t ), intent(in) :: array (:) Return Value logical public function string_cat (strings, delim) result(cat) Concatenate an array of type(string_t) into\n a single CHARACTER variable Arguments Type Intent Optional Attributes Name type( string_t ), intent(in) :: strings (:) character(len=*), intent(in), optional :: delim Return Value character(len=:), allocatable public pure function to_fortran_name (string) result(res) Returns string with special characters replaced with an underscore.\nFor now, only a hyphen is treated as a special character, but this can be\nexpanded to other characters if needed. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string Return Value character(len=len(string)) public pure elemental function upper (str, begin, end) result(string) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: str integer, intent(in), optional :: begin integer, intent(in), optional :: end Return Value character(len=len(str)) Subroutines public impure elemental subroutine notabs (instr, outstr, ilen) Author John S. Urban License Public Domain notabs(3f) - [fpm_strings:NONALPHA] expand tab characters\n (LICENSE:PD) Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: instr character(len=*), intent(out) :: outstr integer, intent(out) :: ilen public subroutine remove_characters_in_set (string, set, replace_with) Arguments Type Intent Optional Attributes Name character(len=:), intent(inout), allocatable :: string character(len=*), intent(in) :: set character(len=1), intent(in), optional :: replace_with public subroutine remove_newline_characters (string) Arguments Type Intent Optional Attributes Name type( string_t ), intent(inout) :: string public subroutine split (input_line, array, delimiters, order, nulls) Author John S. Urban License Public Domain parse string on delimiter characters and store tokens into an allocatable array\ngiven a line of structure ” par1 par2 par3 … parn ” store each par(n) into a separate variable in array. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: input_line input string to tokenize character(len=:), intent(out), allocatable :: array (:) output array of tokens character(len=*), intent(in), optional :: delimiters list of delimiter characters character(len=*), intent(in), optional :: order order of output array sequential|[reverse|right] character(len=*), intent(in), optional :: nulls return strings composed of delimiters or not ignore|return|ignoreend public pure subroutine split_first_last (string, set, first, last) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: string character(len=*), intent(in) :: set integer, intent(out), allocatable :: first (:) integer, intent(out), allocatable :: last (:)","tags":"","loc":"module/fpm_strings.html"},{"title":"fpm_environment – Fortran-lang/fpm","text":"This module contains procedures that interact with the programming environment. [get_os_type] – Determine the OS type [get_env] – return the value of an environment variable Uses fpm_error iso_fortran_env iso_c_binding Variables Type Visibility Attributes Name Initial integer, public, parameter :: OS_CYGWIN = 4 integer, public, parameter :: OS_FREEBSD = 6 integer, public, parameter :: OS_LINUX = 1 integer, public, parameter :: OS_MACOS = 2 integer, public, parameter :: OS_OPENBSD = 7 integer, public, parameter :: OS_SOLARIS = 5 integer, public, parameter :: OS_UNKNOWN = 0 integer, public, parameter :: OS_WINDOWS = 3 Functions public pure function OS_NAME (os) Return string describing the OS type flag Arguments Type Intent Optional Attributes Name integer, intent(in) :: os Return Value character(len=:), allocatable public function delete_env (name) result(success) Deletes an environment variable for the current environment using the C standard library\nReturns an error if the variable did not exist in the first place Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Variable name Return Value logical public function get_command_arguments_quoted () result(args) Arguments None Return Value character(len=:), allocatable public function get_env (NAME, DEFAULT) result(VALUE) get named environment variable value. It it is blank or\n not set return the optional default value\n!print , NAME, ” is not defined in the environment. Strange…”\n!print , “This processor doesn’t support environment variables. Boooh!” Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: NAME name of environment variable to get the value of character(len=*), intent(in), optional :: DEFAULT default value to return if the requested value is undefined or blank Return Value character(len=:), allocatable the returned value public function get_os_type () result(r) Determine the OS type Read more… Arguments None Return Value integer public function os_is_unix (os) Compare the output of get_os_type or the optional\npassed INTEGER value to the value for OS_WINDOWS\nand return .TRUE. if they match and .FALSE. otherwise Arguments Type Intent Optional Attributes Name integer, intent(in), optional :: os Return Value logical public function separator () result(sep) sample usage Read more… Arguments None Return Value character(len=1) ifort_bug*!character(len=1),save :: sep_cache=’ ‘ public function set_env (name, value, overwrite) Set an environment variable for the current environment using the C standard library Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: name Variable name character(len=*), intent(in) :: value Variable value logical, intent(in), optional :: overwrite Should a former value be overwritten? default = .true. Return Value logical","tags":"","loc":"module/fpm_environment.html"},{"title":"fpm_backend – Fortran-lang/fpm","text":"Build backend Uses a list of [[build_target_ptr]] and a valid [[fpm_model]] instance\n to schedule and execute the compilation and linking of package targets. The package build process ( [[build_package]] ) comprises three steps: Target sorting: topological sort of the target dependency graph ( [[sort_target]] ) Target scheduling: group targets into schedule regions based on the sorting ( [[schedule_targets]] ) Target building: generate targets by compilation or linking @note Note\n If compiled with OpenMP, targets will be build in parallel where possible. Incremental compilation The backend process supports incremental compilation whereby targets are not\n re-compiled if their corresponding dependencies have not been modified. Source-based targets ( i.e. objects) are not re-compiled if the corresponding source\n file is unmodified AND all of the target dependencies are not marked for re-compilation Link targets ( i.e. executables and libraries) are not re-compiled if the\n target output file already exists AND all of the target dependencies are not marked for\n re-compilation Source file modification is determined by a file digest (hash) which is calculated during\n the source parsing phase ( fpm_source_parsing ) and cached to disk after a target is\n successfully generated. Uses fpm_targets iso_fortran_env fpm_model fpm_strings fpm_error fpm_backend_output fpm_filesystem Subroutines public subroutine build_package (targets, model, verbose) Top-level routine to build package described by model Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(inout) :: targets (:) type( fpm_model_t ), intent(in) :: model logical, intent(in) :: verbose public subroutine schedule_targets (queue, schedule_ptr, targets) Construct a build schedule from the sorted targets. Read more… Arguments Type Intent Optional Attributes Name type( build_target_ptr ), intent(out), allocatable :: queue (:) integer, allocatable :: schedule_ptr (:) type( build_target_ptr ), intent(in) :: targets (:) public recursive subroutine sort_target (target) Topologically sort a target for scheduling by\n recursing over its dependencies. Read more… Arguments Type Intent Optional Attributes Name type( build_target_t ), intent(inout), target :: target","tags":"","loc":"module/fpm_backend.html"},{"title":"fpm_manifest_fortran – Fortran-lang/fpm","text":"Uses fpm_error fpm_toml Derived Types type, public, extends( serializable_t ) :: fortran_config_t Configuration data for Fortran Components Type Visibility Attributes Name Initial logical, public :: implicit_external = .false. Enable implicit external interfaces logical, public :: implicit_typing = .false. Enable default implicit typing character(len=:), public, allocatable :: source_form Form to use for all Fortran sources Type-Bound Procedures generic, public :: dump => dump_to_toml , dump_to_file, dump_to_unit procedure, public :: dump_to_toml generic, public :: load => load_from_toml , load_from_file, load_from_unit procedure, public :: load_from_toml generic, public :: operator(==) => serializable_is_same procedure, public :: serializable_is_same => fortran_is_same ../../ Serialization interface procedure, public, non_overridable :: test_serialization ../../ Test load/write roundtrip Subroutines public subroutine new_fortran_config (self, table, error) Construct a new build configuration from a TOML data structure Arguments Type Intent Optional Attributes Name type( fortran_config_t ), intent(out) :: self Instance of the fortran configuration type(toml_table), intent(inout) :: table Instance of the TOML data structure type( error_t ), intent(out), allocatable :: error Error handling","tags":"","loc":"module/fpm_manifest_fortran.html"},{"title":"fpm – Fortran-lang/fpm","text":"Uses fpm_targets iso_fortran_env fpm_backend fpm_meta fpm_sources iso_c_binding fpm_environment fpm_toml fpm_settings fpm_command_line fpm_manifest fpm_dependency fpm_model fpm_strings fpm_error fpm_compiler fpm_filesystem Subroutines public subroutine build_model (model, settings, package, error) Constructs a valid fpm model from command line settings and the toml manifest.\nAdd this dependency’s manifest macros Read more… Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(out) :: model class( fpm_build_settings ), intent(inout) :: settings type( package_config_t ), intent(inout) :: package type( error_t ), intent(out), allocatable :: error public subroutine check_modules_for_duplicates (model, duplicates_found) Arguments Type Intent Optional Attributes Name type( fpm_model_t ), intent(in) :: model logical :: duplicates_found public subroutine cmd_build (settings) Dump model to file Arguments Type Intent Optional Attributes Name type( fpm_build_settings ), intent(inout) :: settings public subroutine cmd_clean (settings) Delete the build directory including or excluding dependencies. Can be used\nto clear the registry cache. Arguments Type Intent Optional Attributes Name class( fpm_clean_settings ), intent(in) :: settings Settings for the clean command. public subroutine cmd_run (settings, test) Arguments Type Intent Optional Attributes Name class( fpm_run_settings ), intent(inout) :: settings logical, intent(in) :: test","tags":"","loc":"module/fpm.html"},{"title":"fpm_filesystem – Fortran-lang/fpm","text":"This module contains general routines for interacting with the file system Directories are not files for the Intel compilers. If so, also use this compiler-dependent extension Uses iso_fortran_env fpm_environment iso_c_binding fpm_strings fpm_error Functions public function basename (path, suffix) result(base) Extract filename from path with/without suffix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path logical, intent(in), optional :: suffix Return Value character(len=:), allocatable public function canon_path (path) Canonicalize path for comparison\n* Handles path string redundancies\n* Does not test existence of path Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function dirname (path) result(dir) Extract dirname from path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function exists (filename) result(r) test if pathname already exists Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value logical public function get_dos_path (path, error) Ensure a windows path is converted to an 8.3 DOS path if it contains spaces\nNo need to convert if there are no spaces Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path type( error_t ), intent(out), allocatable :: error Return Value character(len=:), allocatable public function get_local_prefix (os) result(prefix) Determine the path prefix to the local folder. Used for installation, registry etc. Arguments Type Intent Optional Attributes Name integer, intent(in), optional :: os Platform identifier Return Value character(len=:), allocatable Installation prefix public function get_temp_filename () result(tempfile) Get a unused temporary filename\n Calls posix ‘tempnam’ - not recommended, but\n we have no security concerns for this application\n and use here is temporary.\nWorks with MinGW Arguments None Return Value character(len=:), allocatable public function is_absolute_path (path, is_unix) Returns .true. if provided path is absolute. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path logical, intent(in), optional :: is_unix Return Value logical public function is_dir (dir) test if a name matches an existing directory path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir Return Value logical public function is_hidden_file (file_basename) result(r) test if a file is hidden Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file_basename Return Value logical public function join_path (a1, a2, a3, a4, a5) result(path) Construct path by joining strings with os file separator Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: a1 character(len=*), intent(in) :: a2 character(len=*), intent(in), optional :: a3 character(len=*), intent(in), optional :: a4 character(len=*), intent(in), optional :: a5 Return Value character(len=:), allocatable public function number_of_rows (s) result(nrows) Determine number or rows in a file given a LUN Arguments Type Intent Optional Attributes Name integer, intent(in) :: s Return Value integer public function parent_dir (path) result(dir) Extract dirname from path Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function read_lines (filename) result(lines) read lines into an array of TYPE(STRING_T) variables Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value type( string_t ), allocatable, (:) public function read_lines_expanded (filename) result(lines) read lines into an array of TYPE(STRING_T) variables expanding tabs Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename Return Value type( string_t ), allocatable, (:) public function unix_path (path) result(nixpath) Replace file system separators for unix Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable public function which (command) result(pathname) Author John S. Urban License Public Domain function which(command) result(pathname) Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: command Return Value character(len=:), allocatable public function windows_path (path) result(winpath) Replace file system separators for windows Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: path Return Value character(len=:), allocatable Subroutines public subroutine delete_file (file) delete a file by filename Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: file public subroutine execute_and_read_output (cmd, output, error, verbose) Execute command line and return output as a string. Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: cmd Command to execute. character(len=:), intent(out), allocatable :: output Command line output. type( error_t ), intent(out), allocatable :: error Error to handle. logical, intent(in), optional :: verbose Print additional information if true. public subroutine fileclose (lun, ier) simple close of a LUN. On error show message and stop (by default) Arguments Type Intent Optional Attributes Name integer, intent(in) :: lun integer, intent(out), optional :: ier public subroutine fileopen (filename, lun, ier) procedure to open filename as a sequential “text” file Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename integer, intent(out) :: lun integer, intent(out), optional :: ier public subroutine filewrite (filename, filedata) procedure to write filedata to file filename Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: filename character(len=*), intent(in) :: filedata (:) public subroutine get_home (home, error) Get the HOME directory on Unix and the %USERPROFILE% directory on Windows. Arguments Type Intent Optional Attributes Name character(len=:), intent(out), allocatable :: home type( error_t ), intent(out), allocatable :: error public subroutine getline (unit, line, iostat, iomsg) Author fpm(1) contributors License MIT subroutine getline(unit,line,iostat,iomsg) Read more… Arguments Type Intent Optional Attributes Name integer, intent(in) :: unit Formatted IO unit character(len=:), intent(out), allocatable :: line Line to read integer, intent(out) :: iostat Status of operation character(len=:), optional, allocatable :: iomsg Error message public recursive subroutine list_files (dir, files, recurse) Get file & directory names in directory dir using iso_c_binding. Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir type( string_t ), intent(out), allocatable :: files (:) logical, intent(in), optional :: recurse public subroutine mkdir (dir, echo) Create a directory. Create subdirectories as needed Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir logical, intent(in), optional :: echo public subroutine os_delete_dir (is_unix, dir, echo) Delete directory using system OS remove directory commands Arguments Type Intent Optional Attributes Name logical, intent(in) :: is_unix character(len=*), intent(in) :: dir logical, intent(in), optional :: echo public subroutine run (cmd, echo, exitstat, verbose, redirect) Author fpm(1) contributors License MIT Execute the specified system command. Optionally Read more… Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: cmd logical, intent(in), optional :: echo integer, intent(out), optional :: exitstat logical, intent(in), optional :: verbose character(len=*), intent(in), optional :: redirect public subroutine warnwrite (fname, data) write trimmed character data to a file if it does not exist Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: fname character(len=*), intent(in) :: data (:)","tags":"","loc":"module/fpm_filesystem.html"},{"title":"main – Fortran-lang/fpm","text":"Uses iso_fortran_env fpm fpm_command_line fpm_cmd_publish fpm_os fpm_cmd_new fpm_cmd_install fpm_error fpm_cmd_export fpm_cmd_update fpm_filesystem Variables Type Attributes Name Initial class( fpm_cmd_settings ), allocatable :: cmd_settings type( error_t ), allocatable :: error character(len=:), allocatable :: project_root character(len=:), allocatable :: pwd_start character(len=:), allocatable :: pwd_working character(len=:), allocatable :: working_dir Functions function has_manifest (dir) Arguments Type Intent Optional Attributes Name character(len=*), intent(in) :: dir Return Value logical Subroutines subroutine get_working_dir (settings, working_dir_) Save access to working directory in settings, in case setting have not been allocated Arguments Type Intent Optional Attributes Name class( fpm_cmd_settings ), intent(in), optional :: settings character(len=:), intent(out), allocatable :: working_dir_ subroutine handle_error (error_) Arguments Type Intent Optional Attributes Name type( error_t ), intent(in), optional :: error_ Source Code program main use , intrinsic :: iso_fortran_env , only : error_unit , output_unit use fpm_command_line , only : & fpm_cmd_settings , & fpm_new_settings , & fpm_build_settings , & fpm_export_settings , & fpm_run_settings , & fpm_test_settings , & fpm_install_settings , & fpm_update_settings , & fpm_clean_settings , & fpm_publish_settings , & get_command_line_settings use fpm_error , only : error_t use fpm_filesystem , only : exists , parent_dir , join_path use fpm , only : cmd_build , cmd_run , cmd_clean use fpm_cmd_install , only : cmd_install use fpm_cmd_export , only : cmd_export use fpm_cmd_new , only : cmd_new use fpm_cmd_update , only : cmd_update use fpm_cmd_publish , only : cmd_publish use fpm_os , only : change_directory , get_current_directory implicit none class ( fpm_cmd_settings ), allocatable :: cmd_settings type ( error_t ), allocatable :: error character ( len = :), allocatable :: pwd_start , pwd_working , working_dir , project_root call get_command_line_settings ( cmd_settings ) call get_current_directory ( pwd_start , error ) call handle_error ( error ) call get_working_dir ( cmd_settings , working_dir ) if ( allocated ( working_dir )) then ! Change working directory if requested if ( len_trim ( working_dir ) > 0 ) then call change_directory ( working_dir , error ) call handle_error ( error ) call get_current_directory ( pwd_working , error ) call handle_error ( error ) write ( output_unit , '(*(a))' ) \"fpm: Entering directory '\" // pwd_working // \"'\" else pwd_working = pwd_start end if else pwd_working = pwd_start end if select type ( settings => cmd_settings ) type is ( fpm_new_settings ) class default if (. not . has_manifest ( pwd_working )) then project_root = pwd_working do while (. not . has_manifest ( project_root )) working_dir = parent_dir ( project_root ) if ( len ( working_dir ) == 0 ) exit project_root = working_dir end do if ( has_manifest ( project_root )) then call change_directory ( project_root , error ) call handle_error ( error ) write ( output_unit , '(*(a))' ) \"fpm: Entering directory '\" // project_root // \"'\" end if end if end select select type ( settings => cmd_settings ) type is ( fpm_new_settings ) call cmd_new ( settings ) type is ( fpm_build_settings ) call cmd_build ( settings ) type is ( fpm_run_settings ) call cmd_run ( settings , test = . false .) type is ( fpm_test_settings ) call cmd_run ( settings , test = . true .) type is ( fpm_export_settings ) call cmd_export ( settings ) type is ( fpm_install_settings ) call cmd_install ( settings ) type is ( fpm_update_settings ) call cmd_update ( settings ) type is ( fpm_clean_settings ) call cmd_clean ( settings ) type is ( fpm_publish_settings ) call cmd_publish ( settings ) end select if ( allocated ( project_root )) then write ( output_unit , '(*(a))' ) \"fpm: Leaving directory '\" // project_root // \"'\" end if if ( pwd_start /= pwd_working ) then write ( output_unit , '(*(a))' ) \"fpm: Leaving directory '\" // pwd_working // \"'\" end if contains function has_manifest ( dir ) character ( len =* ), intent ( in ) :: dir logical :: has_manifest has_manifest = exists ( join_path ( dir , \"fpm.toml\" )) end function has_manifest subroutine handle_error ( error_ ) type ( error_t ), optional , intent ( in ) :: error_ if ( present ( error_ )) then write ( error_unit , '(\"[Error]\", 1x, a)' ) error_ % message stop 1 end if end subroutine handle_error !> Save access to working directory in settings, in case setting have not been allocated subroutine get_working_dir ( settings , working_dir_ ) class ( fpm_cmd_settings ), optional , intent ( in ) :: settings character ( len = :), allocatable , intent ( out ) :: working_dir_ if ( present ( settings )) then working_dir_ = settings % working_dir end if end subroutine get_working_dir end program main","tags":"","loc":"program/main.html"},{"title":"build.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the build configuration data. !> !> A build table can currently have the following fields !> !>```toml !>[build] !>auto-executables = bool !>auto-examples = bool !>auto-tests = bool !>link = [\"lib\"] !>``` module fpm_manifest_build use fpm_error , only : error_t , syntax_error , fatal_error use fpm_strings , only : string_t , len_trim , is_valid_module_prefix , operator ( == ) use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list , serializable_t , & set_value , set_string , set_list implicit none private public :: build_config_t , new_build_config !> Configuration data for build type , extends ( serializable_t ) :: build_config_t !> Automatic discovery of executables logical :: auto_executables = . true . !> Automatic discovery of examples logical :: auto_examples = . true . !> Automatic discovery of tests logical :: auto_tests = . true . !> Enforcing of package module names logical :: module_naming = . false . type ( string_t ) :: module_prefix !> Libraries to link against type ( string_t ), allocatable :: link (:) !> External modules to use type ( string_t ), allocatable :: external_modules (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => build_conf_is_same procedure :: dump_to_toml procedure :: load_from_toml end type build_config_t character ( * ), parameter , private :: class_name = 'build_config_t' contains !> Construct a new build configuration from a TOML data structure subroutine new_build_config ( self , table , package_name , error ) !> Instance of the build configuration type ( build_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Package name character ( len =* ), intent ( in ) :: package_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat call check ( table , package_name , error ) if ( allocated ( error )) return call get_value ( table , \"auto-executables\" , self % auto_executables , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-executables' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"auto-tests\" , self % auto_tests , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-tests' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"auto-examples\" , self % auto_examples , . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'auto-examples' in fpm.toml, expecting logical\" ) return end if !> Module naming: fist, attempt boolean value first call get_value ( table , \"module-naming\" , self % module_naming , . false ., stat = stat ) if ( stat == toml_stat % success ) then ! Boolean value found. Set no custom prefix. This also falls back to key not provided if ( allocated ( self % module_prefix % s )) deallocate ( self % module_prefix % s ) else !> Value found, but not a boolean. Attempt to read a prefix string call get_value ( table , \"module-naming\" , self % module_prefix % s ) if (. not . allocated ( self % module_prefix % s )) then call syntax_error ( error , \"Could not read value for 'module-naming' in fpm.toml, expecting logical or a string\" ) return end if if (. not . is_valid_module_prefix ( self % module_prefix )) then call syntax_error ( error , \"Invalid custom module name prefix for in fpm.toml: <\" // self % module_prefix % s // & \">, expecting a valid alphanumeric string\" ) return end if ! Set module naming to ON self % module_naming = . true . end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return call get_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return end subroutine new_build_config !> Check local schema for allowed entries subroutine check ( table , package_name , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Package name character ( len =* ), intent ( in ) :: package_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_keys ( list ) ! table can be empty if ( size ( list ) < 1 ) return do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case ( \"auto-executables\" , \"auto-examples\" , \"auto-tests\" , \"link\" , \"external-modules\" , \"module-naming\" ) continue case default call syntax_error ( error , 'Manifest file syntax error: key \"' // list ( ikey )% key // '\" found in the [build] ' // & 'section of package/dependency \"' // package_name // '\" fpm.toml is not allowed' ) exit end select end do end subroutine check !> Write information on build configuration instance subroutine info ( self , unit , verbosity ) !> Instance of the build configuration class ( build_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ilink , imod character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Build configuration\" write ( unit , fmt ) \" - auto-discovery (apps) \" , merge ( \"enabled \" , \"disabled\" , self % auto_executables ) write ( unit , fmt ) \" - auto-discovery (examples) \" , merge ( \"enabled \" , \"disabled\" , self % auto_examples ) write ( unit , fmt ) \" - auto-discovery (tests) \" , merge ( \"enabled \" , \"disabled\" , self % auto_tests ) write ( unit , fmt ) \" - enforce module naming \" , merge ( \"enabled \" , \"disabled\" , self % module_naming ) if ( allocated ( self % link )) then write ( unit , fmt ) \" - link against\" do ilink = 1 , size ( self % link ) write ( unit , fmt ) \" - \" // self % link ( ilink )% s end do end if if ( allocated ( self % external_modules )) then write ( unit , fmt ) \" - external modules\" do imod = 1 , size ( self % external_modules ) write ( unit , fmt ) \" - \" // self % external_modules ( imod )% s end do end if end subroutine info !> Check that two dependency trees are equal logical function build_conf_is_same ( this , that ) class ( build_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that build_conf_is_same = . false . select type ( other => that ) type is ( build_config_t ) if ( this % auto_executables . neqv . other % auto_executables ) return if ( this % auto_examples . neqv . other % auto_examples ) return if ( this % auto_tests . neqv . other % auto_tests ) return if ( this % module_naming . neqv . other % module_naming ) return if (. not . this % module_prefix == other % module_prefix ) return if (. not . this % link == other % link ) return if (. not . this % external_modules == other % external_modules ) return class default ! Not the same type return end select !> All checks passed! build_conf_is_same = . true . end function build_conf_is_same !> Dump build config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( build_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_value ( table , \"auto-executables\" , self % auto_executables , error , class_name ) if ( allocated ( error )) return call set_value ( table , \"auto-tests\" , self % auto_tests , error , class_name ) if ( allocated ( error )) return call set_value ( table , \"auto-examples\" , self % auto_examples , error , class_name ) if ( allocated ( error )) return ! Module naming can either contain a boolean value, or the prefix has_prefix : if ( self % module_naming . and . len_trim ( self % module_prefix ) > 0 ) then call set_string ( table , \"module-naming\" , self % module_prefix , error , class_name ) else call set_value ( table , \"module-naming\" , self % module_naming , error , class_name ) end if has_prefix if ( allocated ( error )) return call set_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return call set_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read build config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( build_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat call get_value ( table , \"auto-executables\" , self % auto_executables , error , class_name ) if ( allocated ( error )) return call get_value ( table , \"auto-tests\" , self % auto_tests , error , class_name ) if ( allocated ( error )) return call get_value ( table , \"auto-examples\" , self % auto_examples , error , class_name ) if ( allocated ( error )) return !> Module naming: fist, attempt boolean value first call get_value ( table , \"module-naming\" , self % module_naming , . false ., stat = stat ) if ( stat == toml_stat % success ) then ! Boolean value found. Set no custom prefix. This also falls back to key not provided if ( allocated ( self % module_prefix % s )) deallocate ( self % module_prefix % s ) else !> Value found, but not a boolean. Attempt to read a prefix string call get_value ( table , \"module-naming\" , self % module_prefix % s ) if (. not . allocated ( self % module_prefix % s )) then call syntax_error ( error , \"Could not read value for 'module-naming' in fpm.toml, expecting logical or a string\" ) return end if self % module_naming = . true . end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return call get_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return end subroutine load_from_toml end module fpm_manifest_build","tags":"","loc":"sourcefile/build.f90.html"},{"title":"install.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the installation configuration. !> !> An install table can currently have the following fields !> !>```toml !>library = bool !>``` module fpm_manifest_install use fpm_error , only : error_t , fatal_error , syntax_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , set_value , serializable_t implicit none private public :: install_config_t , new_install_config !> Configuration data for installation type , extends ( serializable_t ) :: install_config_t !> Install library with this project logical :: library = . false . contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => install_conf_same procedure :: dump_to_toml procedure :: load_from_toml end type install_config_t character ( * ), parameter , private :: class_name = 'install_config_t' contains !> Create a new installation configuration from a TOML data structure subroutine new_install_config ( self , table , error ) !> Instance of the install configuration type ( install_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"library\" , self % library , . false .) end subroutine new_install_config !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_keys ( list ) if ( size ( list ) < 1 ) return do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in install table\" ) exit case ( \"library\" ) continue end select end do if ( allocated ( error )) return end subroutine check !> Write information on install configuration instance subroutine info ( self , unit , verbosity ) !> Instance of the build configuration class ( install_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Install configuration\" write ( unit , fmt ) \" - library install\" , & & trim ( merge ( \"enabled \" , \"disabled\" , self % library )) end subroutine info logical function install_conf_same ( this , that ) class ( install_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that install_conf_same = . false . select type ( other => that ) type is ( install_config_t ) if ( this % library . neqv . other % library ) return class default ! Not the same type return end select !> All checks passed! install_conf_same = . true . end function install_conf_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( install_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_value ( table , \"library\" , self % library , error , class_name ) end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( install_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat call get_value ( table , \"library\" , self % library , error , class_name ) if ( allocated ( error )) return end subroutine load_from_toml end module fpm_manifest_install","tags":"","loc":"sourcefile/install.f90.html"},{"title":"dependency.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for dependencies. !> !> A dependency table can currently have the following fields !> !>```toml !>[dependencies] !>\"dep1\" = { git = \"url\" } !>\"dep2\" = { git = \"url\", branch = \"name\" } !>\"dep3\" = { git = \"url\", tag = \"name\" } !>\"dep4\" = { git = \"url\", rev = \"sha1\" } !>\"dep0\" = { path = \"path\" } !>``` !> !> To reduce the amount of boilerplate code this module provides two constructors !> for dependency types, one basic for an actual dependency (inline) table !> and another to collect all dependency objects from a dependencies table, !> which is handling the allocation of the objects and is forwarding the !> individual dependency tables to their respective constructors. !> The usual entry point should be the constructor for the super table. !> !> This objects contains a target to retrieve required `fpm` projects to !> build the target declaring the dependency. !> Resolving a dependency will result in obtaining a new package configuration !> data for the respective project. module fpm_manifest_dependency use fpm_error , only : error_t , syntax_error , fatal_error use fpm_git , only : git_target_t , git_target_tag , git_target_branch , & & git_target_revision , git_target_default , git_matches_manifest use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , check_keys , serializable_t , add_table , & & set_value , set_string use fpm_filesystem , only : windows_path , join_path use fpm_environment , only : get_os_type , OS_WINDOWS use fpm_manifest_metapackages , only : metapackage_config_t , is_meta_package , new_meta_config , & metapackage_request_t , new_meta_request use fpm_versioning , only : version_t , new_version use fpm_strings , only : string_t use fpm_manifest_preprocess implicit none private public :: dependency_config_t , new_dependency , new_dependencies , manifest_has_changed , & & dependency_destroy , resize !> Configuration meta data for a dependency type , extends ( serializable_t ) :: dependency_config_t !> Name of the dependency character ( len = :), allocatable :: name !> Local target character ( len = :), allocatable :: path !> Namespace which the dependency belongs to. !> Enables multiple dependencies with the same name. !> Required for dependencies that are obtained via the official registry. character ( len = :), allocatable :: namespace !> The requested version of the dependency. !> The latest version is used if not specified. type ( version_t ), allocatable :: requested_version !> Requested macros for the dependency type ( preprocess_config_t ), allocatable :: preprocess (:) !> Git descriptor type ( git_target_t ), allocatable :: git contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => dependency_is_same procedure :: dump_to_toml procedure :: load_from_toml end type dependency_config_t !> Common output format for writing to the command line character ( len =* ), parameter :: out_fmt = '(\"#\", *(1x, g0))' interface resize module procedure resize_dependency_config end interface resize contains !> Construct a new dependency configuration from a TOML data structure subroutine new_dependency ( self , table , root , error ) !> Instance of the dependency configuration type ( dependency_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( * ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: uri , value , requested_version type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call table % get_key ( self % name ) call get_value ( table , \"namespace\" , self % namespace ) call get_value ( table , \"v\" , requested_version ) if ( allocated ( requested_version )) then if (. not . allocated ( self % requested_version )) allocate ( self % requested_version ) call new_version ( self % requested_version , requested_version , error ) if ( allocated ( error )) return end if !> Get optional preprocessor directives call get_value ( table , \"preprocess\" , child , requested = . false .) if ( associated ( child )) then call new_preprocessors ( self % preprocess , child , error ) if ( allocated ( error )) return endif call get_value ( table , \"path\" , uri ) if ( allocated ( uri )) then if ( get_os_type () == OS_WINDOWS ) uri = windows_path ( uri ) if ( present ( root )) uri = join_path ( root , uri ) ! Relative to the fpm.toml it’s written in call move_alloc ( uri , self % path ) return end if call get_value ( table , \"git\" , uri ) if ( allocated ( uri )) then call get_value ( table , \"tag\" , value ) if ( allocated ( value )) then self % git = git_target_tag ( uri , value ) end if if (. not . allocated ( self % git )) then call get_value ( table , \"branch\" , value ) if ( allocated ( value )) then self % git = git_target_branch ( uri , value ) end if end if if (. not . allocated ( self % git )) then call get_value ( table , \"rev\" , value ) if ( allocated ( value )) then self % git = git_target_revision ( uri , value ) end if end if if (. not . allocated ( self % git )) then self % git = git_target_default ( uri ) end if return end if end subroutine new_dependency !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: name type ( toml_key ), allocatable :: list (:) type ( toml_table ), pointer :: child !> List of valid keys for the dependency table. character ( * ), dimension ( * ), parameter :: valid_keys = [ character ( 24 ) :: & & \"namespace\" , & \"v\" , & \"path\" , & \"git\" , & \"tag\" , & \"branch\" , & \"rev\" , & \"preprocess\" & & ] call table % get_key ( name ) call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Dependency '\" // name // \"' does not provide sufficient entries\" ) return end if call check_keys ( table , valid_keys , error ) if ( allocated ( error )) return if ( table % has_key ( \"path\" ) . and . table % has_key ( \"git\" )) then call syntax_error ( error , \"Dependency '\" // name // \"' cannot have both git and path entries\" ) return end if if (( table % has_key ( \"branch\" ) . and . table % has_key ( \"rev\" )) . or . & ( table % has_key ( \"branch\" ) . and . table % has_key ( \"tag\" )) . or . & ( table % has_key ( \"rev\" ) . and . table % has_key ( \"tag\" ))) then call syntax_error ( error , \"Dependency '\" // name // \"' can only have one of branch, rev or tag present\" ) return end if if (( table % has_key ( \"branch\" ) . or . table % has_key ( \"tag\" ) . or . table % has_key ( \"rev\" )) & . and . . not . table % has_key ( \"git\" )) then call syntax_error ( error , \"Dependency '\" // name // \"' has git identifier but no git url\" ) return end if if (. not . table % has_key ( \"path\" ) . and . . not . table % has_key ( \"git\" ) & . and . . not . table % has_key ( \"namespace\" )) then call syntax_error ( error , \"Please provide a 'namespace' for dependency '\" // name // & & \"' if it is not a local path or git repository\" ) return end if if ( table % has_key ( 'v' ) . and . ( table % has_key ( 'path' ) . or . table % has_key ( 'git' ))) then call syntax_error ( error , \"Dependency '\" // name // \"' cannot have both v and git/path entries\" ) return end if ! Check preprocess key if ( table % has_key ( 'preprocess' )) then call get_value ( table , 'preprocess' , child ) if (. not . associated ( child )) then call syntax_error ( error , \"Dependency '\" // name // \"' has invalid 'preprocess' entry\" ) return end if end if end subroutine check !> Construct new dependency array from a TOML data structure subroutine new_dependencies ( deps , table , root , meta , error ) !> Instance of the dependency configuration type ( dependency_config_t ), allocatable , intent ( out ) :: deps (:) !> (optional) metapackages type ( metapackage_config_t ), optional , intent ( out ) :: meta !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( * ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: node type ( toml_key ), allocatable :: list (:) type ( dependency_config_t ), allocatable :: all_deps (:) type ( metapackage_request_t ) :: meta_request logical , allocatable :: is_meta (:) logical :: metapackages_allowed integer :: idep , stat , ndep call table % get_keys ( list ) ! An empty table is okay if ( size ( list ) < 1 ) return !> Flag dependencies that should be treated as metapackages metapackages_allowed = present ( meta ) allocate ( is_meta ( size ( list )), source = . false .) allocate ( all_deps ( size ( list ))) !> Parse all meta- and non-metapackage dependencies do idep = 1 , size ( list ) ! Check if this is a standard dependency node call get_value ( table , list ( idep )% key , node , stat = stat ) is_standard_dependency : if ( stat /= toml_stat % success ) then ! See if it can be a valid metapackage name call new_meta_request ( meta_request , list ( idep )% key , table , error = error ) !> Neither a standard dep nor a metapackage if ( allocated ( error )) then call syntax_error ( error , \"Dependency \" // list ( idep )% key // \" is not a valid metapackage or a table entry\" ) return endif !> Valid meta dependency is_meta ( idep ) = . true . else ! Parse as a standard dependency is_meta ( idep ) = . false . call new_dependency ( all_deps ( idep ), node , root , error ) if ( allocated ( error )) return end if is_standard_dependency end do ! Non-meta dependencies ndep = count (. not . is_meta ) ! Finalize standard dependencies allocate ( deps ( ndep )) ndep = 0 do idep = 1 , size ( list ) if ( is_meta ( idep )) cycle ndep = ndep + 1 deps ( ndep ) = all_deps ( idep ) end do ! Finalize meta dependencies if ( metapackages_allowed ) call new_meta_config ( meta , table , is_meta , error ) end subroutine new_dependencies !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the dependency configuration class ( dependency_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if write ( unit , fmt ) \"Dependency\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % git )) then write ( unit , fmt ) \"- kind\" , \"git\" call self % git % info ( unit , pr - 1 ) end if if ( allocated ( self % path )) then write ( unit , fmt ) \"- kind\" , \"local\" write ( unit , fmt ) \"- path\" , self % path end if end subroutine info !> Check if two dependency configurations are different logical function manifest_has_changed ( cached , manifest , verbosity , iunit ) result ( has_changed ) !> Two instances of the dependency configuration class ( dependency_config_t ), intent ( in ) :: cached , manifest !> Log verbosity integer , intent ( in ) :: verbosity , iunit has_changed = . true . !> Perform all checks if ( allocated ( cached % git ). neqv . allocated ( manifest % git )) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT presence has changed. \" return endif if ( allocated ( cached % git )) then if (. not . git_matches_manifest ( cached % git , manifest % git , verbosity , iunit )) return end if !> All checks passed! The two instances are equal has_changed = . false . end function manifest_has_changed !> Clean memory elemental subroutine dependency_destroy ( self ) class ( dependency_config_t ), intent ( inout ) :: self if ( allocated ( self % name )) deallocate ( self % name ) if ( allocated ( self % path )) deallocate ( self % path ) if ( allocated ( self % namespace )) deallocate ( self % namespace ) if ( allocated ( self % requested_version )) deallocate ( self % requested_version ) if ( allocated ( self % git )) deallocate ( self % git ) end subroutine dependency_destroy !> Check that two dependency configs are equal logical function dependency_is_same ( this , that ) class ( dependency_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that dependency_is_same = . false . select type ( other => that ) type is ( dependency_config_t ) if (. not .( this % name == other % name )) return if (. not .( this % path == other % path )) return if (. not .( this % namespace == other % namespace )) return if (. not .( allocated ( this % requested_version ). eqv . allocated ( other % requested_version ))) return if ( allocated ( this % requested_version )) then if (. not .( this % requested_version == other % requested_version )) return endif if (. not .( allocated ( this % git ). eqv . allocated ( other % git ))) return if ( allocated ( this % git )) then if (. not .( this % git == other % git )) return endif class default ! Not the same type return end select !> All checks passed! dependency_is_same = . true . end function dependency_is_same !> Dump dependency to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( toml_table ), pointer :: ptr type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_string ( table , \"name\" , self % name , error , 'dependency_config_t' ) if ( allocated ( error )) return call set_string ( table , \"path\" , self % path , error , 'dependency_config_t' ) if ( allocated ( error )) return call set_string ( table , \"namespace\" , self % namespace , error , 'dependency_config_t' ) if ( allocated ( error )) return if ( allocated ( self % requested_version )) then call set_string ( table , \"requested_version\" , self % requested_version % s (), error , 'dependency_config_t' ) if ( allocated ( error )) return endif if ( allocated ( self % git )) then call add_table ( table , \"git\" , ptr , error ) if ( allocated ( error )) return call self % git % dump_to_toml ( ptr , error ) if ( allocated ( error )) return endif end subroutine dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables type ( toml_key ), allocatable :: list (:) type ( toml_table ), pointer :: ptr character ( len = :), allocatable :: requested_version integer :: ierr , ii call dependency_destroy ( self ) call get_value ( table , \"name\" , self % name ) call get_value ( table , \"path\" , self % path ) call get_value ( table , \"namespace\" , self % namespace ) call get_value ( table , \"requested_version\" , requested_version ) if ( allocated ( requested_version )) then allocate ( self % requested_version ) call new_version ( self % requested_version , requested_version , error ) if ( allocated ( error )) then error % message = 'dependency_config_t: version error from TOML table - ' // error % message return endif end if call table % get_keys ( list ) add_git : do ii = 1 , size ( list ) if ( list ( ii )% key == \"git\" ) then call get_value ( table , list ( ii )% key , ptr , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'dependency_config_t: cannot retrieve git from TOML table' ) exit endif allocate ( self % git ) call self % git % load_from_toml ( ptr , error ) if ( allocated ( error )) return exit add_git end if end do add_git end subroutine load_from_toml !> Reallocate a list of dependencies pure subroutine resize_dependency_config ( var , n ) !> Instance of the array to be resized type ( dependency_config_t ), allocatable , intent ( inout ) :: var (:) !> Dimension of the final array size integer , intent ( in ), optional :: n type ( dependency_config_t ), allocatable :: tmp (:) integer :: this_size , new_size integer , parameter :: initial_size = 16 if ( allocated ( var )) then this_size = size ( var , 1 ) call move_alloc ( var , tmp ) else this_size = initial_size end if if ( present ( n )) then new_size = n else new_size = this_size + this_size / 2 + 1 end if allocate ( var ( new_size )) if ( allocated ( tmp )) then this_size = min ( size ( tmp , 1 ), size ( var , 1 )) var (: this_size ) = tmp (: this_size ) deallocate ( tmp ) end if end subroutine resize_dependency_config end module fpm_manifest_dependency","tags":"","loc":"sourcefile/dependency.f90.html"},{"title":"main.f90 – Fortran-lang/fpm","text":"Source Code program main use , intrinsic :: iso_fortran_env , only : error_unit , output_unit use fpm_command_line , only : & fpm_cmd_settings , & fpm_new_settings , & fpm_build_settings , & fpm_export_settings , & fpm_run_settings , & fpm_test_settings , & fpm_install_settings , & fpm_update_settings , & fpm_clean_settings , & fpm_publish_settings , & get_command_line_settings use fpm_error , only : error_t use fpm_filesystem , only : exists , parent_dir , join_path use fpm , only : cmd_build , cmd_run , cmd_clean use fpm_cmd_install , only : cmd_install use fpm_cmd_export , only : cmd_export use fpm_cmd_new , only : cmd_new use fpm_cmd_update , only : cmd_update use fpm_cmd_publish , only : cmd_publish use fpm_os , only : change_directory , get_current_directory implicit none class ( fpm_cmd_settings ), allocatable :: cmd_settings type ( error_t ), allocatable :: error character ( len = :), allocatable :: pwd_start , pwd_working , working_dir , project_root call get_command_line_settings ( cmd_settings ) call get_current_directory ( pwd_start , error ) call handle_error ( error ) call get_working_dir ( cmd_settings , working_dir ) if ( allocated ( working_dir )) then ! Change working directory if requested if ( len_trim ( working_dir ) > 0 ) then call change_directory ( working_dir , error ) call handle_error ( error ) call get_current_directory ( pwd_working , error ) call handle_error ( error ) write ( output_unit , '(*(a))' ) \"fpm: Entering directory '\" // pwd_working // \"'\" else pwd_working = pwd_start end if else pwd_working = pwd_start end if select type ( settings => cmd_settings ) type is ( fpm_new_settings ) class default if (. not . has_manifest ( pwd_working )) then project_root = pwd_working do while (. not . has_manifest ( project_root )) working_dir = parent_dir ( project_root ) if ( len ( working_dir ) == 0 ) exit project_root = working_dir end do if ( has_manifest ( project_root )) then call change_directory ( project_root , error ) call handle_error ( error ) write ( output_unit , '(*(a))' ) \"fpm: Entering directory '\" // project_root // \"'\" end if end if end select select type ( settings => cmd_settings ) type is ( fpm_new_settings ) call cmd_new ( settings ) type is ( fpm_build_settings ) call cmd_build ( settings ) type is ( fpm_run_settings ) call cmd_run ( settings , test = . false .) type is ( fpm_test_settings ) call cmd_run ( settings , test = . true .) type is ( fpm_export_settings ) call cmd_export ( settings ) type is ( fpm_install_settings ) call cmd_install ( settings ) type is ( fpm_update_settings ) call cmd_update ( settings ) type is ( fpm_clean_settings ) call cmd_clean ( settings ) type is ( fpm_publish_settings ) call cmd_publish ( settings ) end select if ( allocated ( project_root )) then write ( output_unit , '(*(a))' ) \"fpm: Leaving directory '\" // project_root // \"'\" end if if ( pwd_start /= pwd_working ) then write ( output_unit , '(*(a))' ) \"fpm: Leaving directory '\" // pwd_working // \"'\" end if contains function has_manifest ( dir ) character ( len =* ), intent ( in ) :: dir logical :: has_manifest has_manifest = exists ( join_path ( dir , \"fpm.toml\" )) end function has_manifest subroutine handle_error ( error_ ) type ( error_t ), optional , intent ( in ) :: error_ if ( present ( error_ )) then write ( error_unit , '(\"[Error]\", 1x, a)' ) error_ % message stop 1 end if end subroutine handle_error !> Save access to working directory in settings, in case setting have not been allocated subroutine get_working_dir ( settings , working_dir_ ) class ( fpm_cmd_settings ), optional , intent ( in ) :: settings character ( len = :), allocatable , intent ( out ) :: working_dir_ if ( present ( settings )) then working_dir_ = settings % working_dir end if end subroutine get_working_dir end program main","tags":"","loc":"sourcefile/main.f90.html"},{"title":"versioning.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of versioning data for comparing packages module fpm_versioning use fpm_error , only : error_t , syntax_error use fpm_strings , only : string_t use regex_module , only : regex implicit none private public :: version_t , new_version public :: regex_version_from_text type :: version_t private !> Version numbers found integer , allocatable :: num (:) contains generic :: operator ( == ) => equals procedure , private :: equals generic :: operator ( /= ) => not_equals procedure , private :: not_equals generic :: operator ( > ) => greater procedure , private :: greater generic :: operator ( < ) => less procedure , private :: less generic :: operator ( >= ) => greater_equals procedure , private :: greater_equals generic :: operator ( <= ) => less_equals procedure , private :: less_equals !> Compare a version against a version constraint (x.x.0 <= v < x.x.HUGE) generic :: operator (. match .) => match procedure , private :: match !> Create a printable string from a version data type procedure :: s end type version_t !> Arbitrary internal limit of the version parser integer , parameter :: max_limit = 3 interface new_version module procedure :: new_version_from_string module procedure :: new_version_from_int end interface new_version contains !> Create a new version from a string subroutine new_version_from_int ( self , num ) !> Instance of the versioning data type ( version_t ), intent ( out ) :: self !> Subversion numbers to define version data integer , intent ( in ) :: num (:) self % num = num end subroutine new_version_from_int !> Create a new version from a string subroutine new_version_from_string ( self , string , error ) !> Instance of the versioning data type ( version_t ), intent ( out ) :: self !> String describing the version information character ( len =* ), intent ( in ) :: string !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: istart , iend , stat , nn integer :: num ( max_limit ) logical :: is_number nn = 0 iend = 0 istart = 0 is_number = . false . do while ( iend < len ( string )) call next ( string , istart , iend , is_number , error ) if ( allocated ( error )) exit if ( is_number ) then if ( nn >= max_limit ) then call token_error ( error , string , istart , iend , & & \"Too many subversions found\" ) exit end if nn = nn + 1 read ( string ( istart : iend ), * , iostat = stat ) num ( nn ) if ( stat /= 0 ) then call token_error ( error , string , istart , iend , & & \"Failed to parse version number\" ) exit end if end if end do if ( allocated ( error )) return if (. not . is_number ) then call token_error ( error , string , istart , iend , & & \"Expected version number, but no characters are left\" ) return end if call new_version ( self , num (: nn )) end subroutine new_version_from_string !> Tokenize a version string subroutine next ( string , istart , iend , is_number , error ) !> String describing the version information character ( len =* ), intent ( in ) :: string !> Start of last token, start of next token on exit integer , intent ( inout ) :: istart !> End of last token on entry, end of next token on exit integer , intent ( inout ) :: iend !> Token produced is a number logical , intent ( inout ) :: is_number !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ii , nn logical :: was_number character :: tok was_number = is_number nn = len ( string ) if ( iend >= nn ) then istart = nn iend = nn return end if ii = min ( iend + 1 , nn ) tok = string ( ii : ii ) is_number = tok /= '.' if ( is_number . eqv . was_number ) then call token_error ( error , string , istart , ii , & & \"Unexpected token found\" ) return end if if (. not . is_number ) then is_number = . false . istart = ii iend = ii return end if istart = ii do ii = min ( iend + 1 , nn ), nn tok = string ( ii : ii ) select case ( tok ) case default call token_error ( error , string , istart , ii , & & \"Invalid character in version number\" ) exit case ( '.' ) exit case ( '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ) iend = ii cycle end select end do end subroutine next !> Create an error on an invalid token, provide some visual context as well subroutine token_error ( error , string , istart , iend , message ) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> String describing the version information character ( len =* ), intent ( in ) :: string !> Start of last token, start of next token on exit integer , intent ( in ) :: istart !> End of last token on entry, end of next token on exit integer , intent ( in ) :: iend !> Error message character ( len =* ), intent ( in ) :: message character ( len =* ), parameter :: nl = new_line ( 'a' ) allocate ( error ) error % message = message // nl // \" | \" // string // nl // & & \" |\" // repeat ( '-' , istart ) // repeat ( '^' , iend - istart + 1 ) end subroutine token_error pure function s ( self ) result ( string ) !> Version number class ( version_t ), intent ( in ) :: self !> Character representation of the version character ( len = :), allocatable :: string integer , parameter :: buffersize = 64 character ( len = buffersize ) :: buffer integer :: ii do ii = 1 , ndigits ( self ) if ( allocated ( string )) then write ( buffer , '(\".\", i0)' ) self % num ( ii ) string = string // trim ( buffer ) else write ( buffer , '(i0)' ) self % num ( ii ) string = trim ( buffer ) end if end do if (. not . allocated ( string )) then string = '0' end if end function s !> Check to version numbers for equality elemental function equals ( lhs , rhs ) result ( is_equal ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> Version match logical :: is_equal is_equal = . not .( lhs > rhs ) if ( is_equal ) then is_equal = . not .( rhs > lhs ) end if end function equals !> Check two versions for inequality elemental function not_equals ( lhs , rhs ) result ( not_equal ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> Version mismatch logical :: not_equal not_equal = lhs > rhs if (. not . not_equal ) then not_equal = rhs > lhs end if end function not_equals !> Relative comparison of two versions elemental function greater ( lhs , rhs ) result ( is_greater ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> First version is greater logical :: is_greater integer :: ii , lhs_size , rhs_size do ii = 1 , min ( ndigits ( lhs ), ndigits ( rhs )) if ( lhs % num ( ii ) /= rhs % num ( ii )) then is_greater = lhs % num ( ii ) > rhs % num ( ii ) return end if end do is_greater = ndigits ( lhs ) > ndigits ( rhs ) if ( is_greater ) then do ii = ndigits ( rhs ) + 1 , ndigits ( lhs ) is_greater = lhs % num ( ii ) > 0 if ( is_greater ) return end do end if end function greater !> Relative comparison of two versions elemental function less ( lhs , rhs ) result ( is_less ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> First version is less logical :: is_less is_less = rhs > lhs end function less !> Relative comparison of two versions elemental function greater_equals ( lhs , rhs ) result ( is_greater_equal ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> First version is greater or equal logical :: is_greater_equal is_greater_equal = . not . ( rhs > lhs ) end function greater_equals !> Relative comparison of two versions elemental function less_equals ( lhs , rhs ) result ( is_less_equal ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> First version is less or equal logical :: is_less_equal is_less_equal = . not . ( lhs > rhs ) end function less_equals !> Try to match first version against second version elemental function match ( lhs , rhs ) !> First version number class ( version_t ), intent ( in ) :: lhs !> Second version number class ( version_t ), intent ( in ) :: rhs !> Version match following semantic versioning rules logical :: match type ( version_t ) :: tmp match = . not .( rhs > lhs ) if ( match ) then tmp % num = rhs % num tmp % num ( size ( tmp % num )) = tmp % num ( size ( tmp % num )) + 1 match = tmp > lhs end if end function match !> Number of digits elemental integer function ndigits ( self ) class ( version_t ), intent ( in ) :: self if ( allocated ( self % num )) then ndigits = size ( self % num ) else ndigits = 0 end if end function ndigits ! Extract canonical version flags \"1.0.0\" or \"1.0\" as the first instance inside a text ! (whatever long) using regex type ( string_t ) function regex_version_from_text ( text , what , error ) result ( ver ) character ( * ), intent ( in ) :: text character ( * ), intent ( in ) :: what type ( error_t ), allocatable , intent ( out ) :: error integer :: ire , length if ( len_trim ( text ) <= 0 ) then call syntax_error ( error , 'cannot retrieve ' // what // ' version: empty input string' ) return end if ! Extract 3-sized version \"1.0.4\" ire = regex ( text , '\\d+\\.\\d+\\.\\d+' , length = length ) if ( ire > 0 . and . length > 0 ) then ! Parse version into the object (this should always work) ver = string_t ( text ( ire : ire + length - 1 )) else ! Try 2-sized version \"1.0\" ire = regex ( text , '\\d+\\.\\d+' , length = length ) if ( ire > 0 . and . length > 0 ) then ver = string_t ( text ( ire : ire + length - 1 )) else call syntax_error ( error , 'cannot retrieve ' // what // ' version.' ) end if end if end function regex_version_from_text end module fpm_versioning","tags":"","loc":"sourcefile/versioning.f90.html"},{"title":"git.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation for interacting with git repositories. module fpm_git use fpm_error , only : error_t , fatal_error use fpm_filesystem , only : get_temp_filename , getline , join_path , execute_and_read_output , run use fpm_toml , only : serializable_t , toml_table , get_value , set_value , toml_stat , set_string implicit none public :: git_target_t , git_target_default , git_target_branch , git_target_tag , git_target_revision , git_revision , & & git_archive , git_matches_manifest , operator ( == ), compressed_package_name !> Name of the compressed package that is generated temporarily. character ( len =* ), parameter :: compressed_package_name = 'compressed_package' !> Possible git target type :: enum_descriptor !> Default target integer :: default = 200 !> Branch in git repository integer :: branch = 201 !> Tag in git repository integer :: tag = 202 !> Commit hash integer :: revision = 203 !> Invalid descriptor integer :: error = - 999 end type enum_descriptor !> Actual enumerator for descriptors type ( enum_descriptor ), parameter :: git_descriptor = enum_descriptor () !> Description of an git target type , extends ( serializable_t ) :: git_target_t !> Kind of the git target integer :: descriptor = git_descriptor % default !> Target URL of the git repository character ( len = :), allocatable :: url !> Additional descriptor of the git object character ( len = :), allocatable :: object contains !> Fetch and checkout in local directory procedure :: checkout !> Show information on instance procedure :: info !> Serialization interface procedure :: serializable_is_same => git_is_same procedure :: dump_to_toml procedure :: load_from_toml end type git_target_t !> Common output format for writing to the command line character ( len =* ), parameter :: out_fmt = '(\"#\", *(1x, g0))' contains !> Default target function git_target_default ( url ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % default self % url = url end function git_target_default !> Target a branch in the git repository function git_target_branch ( url , branch ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Name of the branch of interest character ( len =* ), intent ( in ) :: branch !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % branch self % url = url self % object = branch end function git_target_branch !> Target a specific git revision function git_target_revision ( url , sha1 ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Commit hash of interest character ( len =* ), intent ( in ) :: sha1 !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % revision self % url = url self % object = sha1 end function git_target_revision !> Target a git tag function git_target_tag ( url , tag ) result ( self ) !> Target URL of the git repository character ( len =* ), intent ( in ) :: url !> Tag name of interest character ( len =* ), intent ( in ) :: tag !> New git target type ( git_target_t ) :: self self % descriptor = git_descriptor % tag self % url = url self % object = tag end function git_target_tag !> Check that two git targets are equal logical function git_is_same ( this , that ) class ( git_target_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that git_is_same = . false . select type ( other => that ) type is ( git_target_t ) if (. not .( this % descriptor == other % descriptor )) return if (. not .( this % url == other % url )) return if (. not .( this % object == other % object )) return class default ! Not the same type return end select !> All checks passed! git_is_same = . true . end function git_is_same !> Check that a cached dependency matches a manifest request logical function git_matches_manifest ( cached , manifest , verbosity , iunit ) !> Two input git targets type ( git_target_t ), intent ( in ) :: cached , manifest integer , intent ( in ) :: verbosity , iunit git_matches_manifest = cached % url == manifest % url if (. not . git_matches_manifest ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT URL has changed: \" , cached % url , \" vs. \" , manifest % url return endif !> The manifest dependency only contains partial information (what's requested), !> while the cached dependency always stores a commit hash because it's built !> after the repo is available (saved as git_descriptor%revision==revision). !> So, comparing against the descriptor is not reliable git_matches_manifest = allocated ( cached % object ) . eqv . allocated ( manifest % object ) if ( git_matches_manifest . and . allocated ( cached % object )) & git_matches_manifest = cached % object == manifest % object if (. not . git_matches_manifest ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"GIT OBJECT has changed: \" , cached % object , \" vs. \" , manifest % object end if end function git_matches_manifest subroutine checkout ( self , local_path , error ) !> Instance of the git target class ( git_target_t ), intent ( in ) :: self !> Local path to checkout in character ( * ), intent ( in ) :: local_path !> Error type ( error_t ), allocatable , intent ( out ) :: error integer :: stat character ( len = :), allocatable :: object , workdir if ( allocated ( self % object )) then object = self % object else object = 'HEAD' end if workdir = \"--work-tree=\" // local_path // \" --git-dir=\" // join_path ( local_path , \".git\" ) call execute_command_line ( \"git init \" // local_path , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while initiating git repository for remote dependency' ) return end if call execute_command_line ( \"git \" // workdir // \" fetch --depth=1 \" // & self % url // \" \" // object , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while fetching git repository for remote dependency' ) return end if call execute_command_line ( \"git \" // workdir // \" checkout -qf FETCH_HEAD\" , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'Error while checking out git repository for remote dependency' ) return end if end subroutine checkout subroutine git_revision ( local_path , object , error ) !> Local path to checkout in character ( * ), intent ( in ) :: local_path !> Git object reference character ( len = :), allocatable , intent ( out ) :: object !> Error type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , unit , istart , iend character ( len = :), allocatable :: temp_file , line , iomsg , workdir character ( len =* ), parameter :: hexdigits = '0123456789abcdef' workdir = \"--work-tree=\" // local_path // \" --git-dir=\" // join_path ( local_path , \".git\" ) allocate ( temp_file , source = get_temp_filename ()) line = \"git \" // workdir // \" log -n 1 > \" // temp_file call execute_command_line ( line , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error while retrieving commit information\" ) return end if open ( file = temp_file , newunit = unit ) call getline ( unit , line , stat , iomsg ) if ( stat /= 0 ) then call fatal_error ( error , iomsg ) return end if close ( unit , status = \"delete\" ) ! Tokenize: ! commit 0123456789abcdef (HEAD, ...) istart = scan ( line , ' ' ) + 1 iend = verify ( line ( istart :), hexdigits ) + istart - 1 if ( iend < istart ) iend = len ( line ) object = line ( istart : iend ) end subroutine git_revision !> Show information on git target subroutine info ( self , unit , verbosity ) !> Instance of the git target class ( git_target_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Git target\" if ( allocated ( self % url )) then write ( unit , fmt ) \"- URL\" , self % url end if if ( allocated ( self % object )) then select case ( self % descriptor ) case default write ( unit , fmt ) \"- object\" , self % object case ( git_descriptor % tag ) write ( unit , fmt ) \"- tag\" , self % object case ( git_descriptor % branch ) write ( unit , fmt ) \"- branch\" , self % object case ( git_descriptor % revision ) write ( unit , fmt ) \"- sha1\" , self % object end select end if end subroutine info !> Dump dependency to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( git_target_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_string ( table , \"descriptor\" , descriptor_name ( self % descriptor ), error , 'git_target_t' ) if ( allocated ( error )) return call set_string ( table , \"url\" , self % url , error , 'git_target_t' ) if ( allocated ( error )) return call set_string ( table , \"object\" , self % object , error , 'git_target_t' ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( git_target_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: descriptor_name call get_value ( table , \"descriptor\" , descriptor_name ) self % descriptor = parse_descriptor ( descriptor_name ) if ( self % descriptor == git_descriptor % error ) then call fatal_error ( error , \"invalid descriptor ID <\" // descriptor_name // \"> in TOML entry\" ) return end if !> Target URL of the git repository call get_value ( table , \"url\" , self % url ) !> Additional descriptor of the git object call get_value ( table , \"object\" , self % object ) end subroutine load_from_toml !> Parse git descriptor identifier from a string pure integer function parse_descriptor ( name ) character ( len =* ), intent ( in ) :: name select case ( name ) case ( \"default\" ); parse_descriptor = git_descriptor % default case ( \"branch\" ); parse_descriptor = git_descriptor % branch case ( \"tag\" ); parse_descriptor = git_descriptor % tag case ( \"revision\" ); parse_descriptor = git_descriptor % revision case default ; parse_descriptor = git_descriptor % error end select end function parse_descriptor !> Code git descriptor to a string pure function descriptor_name ( descriptor ) result ( name ) integer , intent ( in ) :: descriptor character ( len = :), allocatable :: name select case ( descriptor ) case ( git_descriptor % default ); name = \"default\" case ( git_descriptor % branch ); name = \"branch\" case ( git_descriptor % tag ); name = \"tag\" case ( git_descriptor % revision ); name = \"revision\" case default ; name = \"ERROR\" end select end function descriptor_name !> Archive a folder using `git archive`. subroutine git_archive ( source , destination , ref , additional_files , verbose , error ) !> Directory to archive. character ( * ), intent ( in ) :: source !> Destination of the archive. character ( * ), intent ( in ) :: destination !> (Symbolic) Reference to be archived. character ( * ), intent ( in ) :: ref !> (Optional) list of additional untracked files to be added to the archive. character ( * ), optional , intent ( in ) :: additional_files (:) !> Print additional information if true. logical , intent ( in ) :: verbose !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , i character ( len = :), allocatable :: cmd_output , archive_format , add_files call execute_and_read_output ( 'git archive -l' , cmd_output , error , verbose ) if ( allocated ( error )) return if ( index ( cmd_output , 'tar.gz' ) /= 0 ) then archive_format = 'tar.gz' else call fatal_error ( error , \"Cannot find a suitable archive format for 'git archive'.\" ); return end if allocate ( character ( len = 0 ) :: add_files ) if ( present ( additional_files )) then do i = 1 , size ( additional_files ) add_files = trim ( add_files ) // ' --add-file=' // adjustl ( additional_files ( i )) end do endif call run ( 'git archive ' // ref // ' & & --format=' // archive_format // & & add_files // ' & & -o ' // destination , & & echo = verbose , & & exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error packing '\" // source // \"'.\" ); return end if end end module fpm_git","tags":"","loc":"sourcefile/git.f90.html"},{"title":"installer.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of an installer object. !> !> The installer provides a way to install objects to their respective directories !> in the installation prefix, a generic install command allows to install !> to any directory within the prefix. module fpm_installer use , intrinsic :: iso_fortran_env , only : output_unit use fpm_environment , only : get_os_type , os_is_unix use fpm_error , only : error_t , fatal_error use fpm_filesystem , only : join_path , mkdir , exists , unix_path , windows_path , get_local_prefix implicit none private public :: installer_t , new_installer !> Declaration of the installer type type :: installer_t !> Path to installation directory character ( len = :), allocatable :: prefix !> Binary dir relative to the installation prefix character ( len = :), allocatable :: bindir !> Library directory relative to the installation prefix character ( len = :), allocatable :: libdir !> Include directory relative to the installation prefix character ( len = :), allocatable :: includedir !> Output unit for informative printout integer :: unit = output_unit !> Verbosity of the installer integer :: verbosity = 1 !> Command to copy objects into the installation prefix character ( len = :), allocatable :: copy !> Command to move objects into the installation prefix character ( len = :), allocatable :: move !> Cached operating system integer :: os contains !> Install an executable in its correct subdirectory procedure :: install_executable !> Install a library in its correct subdirectory procedure :: install_library !> Install a header/module in its correct subdirectory procedure :: install_header !> Install a generic file into a subdirectory in the installation prefix procedure :: install !> Run an installation command, type-bound for unit testing purposes procedure :: run !> Create a new directory in the prefix, type-bound for unit testing purposes procedure :: make_dir end type installer_t !> Default name of the binary subdirectory character ( len =* ), parameter :: default_bindir = \"bin\" !> Default name of the library subdirectory character ( len =* ), parameter :: default_libdir = \"lib\" !> Default name of the include subdirectory character ( len =* ), parameter :: default_includedir = \"include\" !> Copy command on Unix platforms character ( len =* ), parameter :: default_copy_unix = \"cp\" !> Copy command on Windows platforms character ( len =* ), parameter :: default_copy_win = \"copy\" !> Copy command on Unix platforms character ( len =* ), parameter :: default_force_copy_unix = \"cp -f\" !> Copy command on Windows platforms character ( len =* ), parameter :: default_force_copy_win = \"copy /Y\" !> Move command on Unix platforms character ( len =* ), parameter :: default_move_unix = \"mv\" !> Move command on Windows platforms character ( len =* ), parameter :: default_move_win = \"move\" contains !> Create a new instance of an installer subroutine new_installer ( self , prefix , bindir , libdir , includedir , verbosity , & copy , move ) !> Instance of the installer type ( installer_t ), intent ( out ) :: self !> Path to installation directory character ( len =* ), intent ( in ), optional :: prefix !> Binary dir relative to the installation prefix character ( len =* ), intent ( in ), optional :: bindir !> Library directory relative to the installation prefix character ( len =* ), intent ( in ), optional :: libdir !> Include directory relative to the installation prefix character ( len =* ), intent ( in ), optional :: includedir !> Verbosity of the installer integer , intent ( in ), optional :: verbosity !> Copy command character ( len =* ), intent ( in ), optional :: copy !> Move command character ( len =* ), intent ( in ), optional :: move self % os = get_os_type () ! By default, never prompt the user for overwrites if ( present ( copy )) then self % copy = copy else if ( os_is_unix ( self % os )) then self % copy = default_force_copy_unix else self % copy = default_force_copy_win end if end if if ( present ( move )) then self % move = move else if ( os_is_unix ( self % os )) then self % move = default_move_unix else self % move = default_move_win end if end if if ( present ( includedir )) then self % includedir = includedir else self % includedir = default_includedir end if if ( present ( prefix )) then self % prefix = prefix else self % prefix = get_local_prefix ( self % os ) end if if ( present ( bindir )) then self % bindir = bindir else self % bindir = default_bindir end if if ( present ( libdir )) then self % libdir = libdir else self % libdir = default_libdir end if if ( present ( verbosity )) then self % verbosity = verbosity else self % verbosity = 1 end if end subroutine new_installer !> Install an executable in its correct subdirectory subroutine install_executable ( self , executable , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Path to the executable character ( len =* ), intent ( in ) :: executable !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ll if (. not . os_is_unix ( self % os )) then ll = len ( executable ) if ( executable ( max ( 1 , ll - 3 ): ll ) /= \".exe\" ) then call self % install ( executable // \".exe\" , self % bindir , error ) return end if end if call self % install ( executable , self % bindir , error ) end subroutine install_executable !> Install a library in its correct subdirectory subroutine install_library ( self , library , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Path to the library character ( len =* ), intent ( in ) :: library !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call self % install ( library , self % libdir , error ) end subroutine install_library !> Install a header/module in its correct subdirectory subroutine install_header ( self , header , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Path to the header character ( len =* ), intent ( in ) :: header !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call self % install ( header , self % includedir , error ) end subroutine install_header !> Install a generic file into a subdirectory in the installation prefix subroutine install ( self , source , destination , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Path to the original file character ( len =* ), intent ( in ) :: source !> Path to the destination inside the prefix character ( len =* ), intent ( in ) :: destination !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: install_dest install_dest = join_path ( self % prefix , destination ) if ( os_is_unix ( self % os )) then install_dest = unix_path ( install_dest ) else install_dest = windows_path ( install_dest ) end if call self % make_dir ( install_dest , error ) if ( allocated ( error )) return if ( self % verbosity > 0 ) then if ( exists ( install_dest )) then write ( self % unit , '(\"# Update:\", 1x, a, 1x, \"->\", 1x, a)' ) & source , install_dest else write ( self % unit , '(\"# Install:\", 1x, a, 1x, \"->\", 1x, a)' ) & source , install_dest end if end if ! Use force-copy to never prompt the user for overwrite if a package was already installed call self % run ( self % copy // ' \"' // source // '\" \"' // install_dest // '\"' , error ) if ( allocated ( error )) return end subroutine install !> Create a new directory in the prefix subroutine make_dir ( self , dir , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Directory to be created character ( len =* ), intent ( in ) :: dir !> Error handling type ( error_t ), allocatable , intent ( out ) :: error if (. not . exists ( dir )) then if ( self % verbosity > 1 ) then write ( self % unit , '(\"# Dir:\", 1x, a)' ) dir end if call mkdir ( dir ) end if end subroutine make_dir !> Run an installation command subroutine run ( self , command , error ) !> Instance of the installer class ( installer_t ), intent ( inout ) :: self !> Command to be launched character ( len =* ), intent ( in ) :: command !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat if ( self % verbosity > 1 ) then write ( self % unit , '(\"# Run:\", 1x, a)' ) command end if call execute_command_line ( command , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed in command: '\" // command // \"'\" ) return end if end subroutine run end module fpm_installer","tags":"","loc":"sourcefile/installer.f90.html"},{"title":"manifest.f90 – Fortran-lang/fpm","text":"Source Code !> Package configuration data. !> !> This module provides the necessary procedure to translate a TOML document !> to the corresponding Fortran type, while verifying it with respect to !> its schema. !> !> Additionally, the required data types for users of this module are reexported !> to hide the actual implementation details. module fpm_manifest use fpm_manifest_example , only : example_config_t use fpm_manifest_executable , only : executable_config_t use fpm_manifest_dependency , only : dependency_config_t use fpm_manifest_library , only : library_config_t use fpm_manifest_preprocess , only : preprocess_config_t use fpm_manifest_package , only : package_config_t , new_package use fpm_error , only : error_t , fatal_error use fpm_toml , only : toml_table , read_package_file use fpm_manifest_test , only : test_config_t use fpm_filesystem , only : join_path , exists , dirname , is_dir use fpm_environment , only : os_is_unix use fpm_strings , only : string_t implicit none private public :: get_package_data , default_executable , default_library , default_test public :: default_example public :: package_config_t , dependency_config_t , preprocess_config_t contains !> Populate library in case we find the default src directory subroutine default_library ( self ) !> Instance of the library meta data type ( library_config_t ), intent ( out ) :: self self % source_dir = \"src\" self % include_dir = [ string_t ( \"include\" )] end subroutine default_library !> Populate executable in case we find the default app directory subroutine default_executable ( self , name ) !> Instance of the executable meta data type ( executable_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name self % source_dir = \"app\" self % main = \"main.f90\" end subroutine default_executable !> Populate test in case we find the default example/ directory subroutine default_example ( self , name ) !> Instance of the executable meta data type ( example_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name // \"-demo\" self % source_dir = \"example\" self % main = \"main.f90\" end subroutine default_example !> Populate test in case we find the default test/ directory subroutine default_test ( self , name ) !> Instance of the executable meta data type ( test_config_t ), intent ( out ) :: self !> Name of the package character ( len =* ), intent ( in ) :: name self % name = name // \"-test\" self % source_dir = \"test\" self % main = \"main.f90\" end subroutine default_test !> Obtain package meta data from a configuation file subroutine get_package_data ( package , file , error , apply_defaults ) !> Parsed package meta data type ( package_config_t ), intent ( out ) :: package !> Name of the package configuration file character ( len =* ), intent ( in ) :: file !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error !> Apply package defaults (uses file system operations) logical , intent ( in ), optional :: apply_defaults type ( toml_table ), allocatable :: table character ( len = :), allocatable :: root call read_package_file ( table , file , error ) if ( allocated ( error )) return if (. not . allocated ( table )) then call fatal_error ( error , \"Unclassified error while reading: '\" // file // \"'\" ) return end if call new_package ( package , table , dirname ( file ), error ) if ( allocated ( error )) return if ( present ( apply_defaults )) then if ( apply_defaults ) then root = dirname ( file ) if ( len_trim ( root ) == 0 ) root = \".\" call package_defaults ( package , root , error ) if ( allocated ( error )) return end if end if end subroutine get_package_data !> Apply package defaults subroutine package_defaults ( package , root , error ) !> Parsed package meta data type ( package_config_t ), intent ( inout ) :: package !> Current working directory character ( len =* ), intent ( in ) :: root !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error ! Populate library in case we find the default src directory if (. not . allocated ( package % library ) . and . & & ( is_dir ( join_path ( root , \"src\" )) . or . & & is_dir ( join_path ( root , \"include\" )))) then allocate ( package % library ) call default_library ( package % library ) end if ! Populate executable in case we find the default app if (. not . allocated ( package % executable ) . and . & & exists ( join_path ( root , \"app\" , \"main.f90\" ))) then allocate ( package % executable ( 1 )) call default_executable ( package % executable ( 1 ), package % name ) end if ! Populate example in case we find the default example directory if (. not . allocated ( package % example ) . and . & & exists ( join_path ( root , \"example\" , \"main.f90\" ))) then allocate ( package % example ( 1 )) call default_example ( package % example ( 1 ), package % name ) endif ! Populate test in case we find the default test directory if (. not . allocated ( package % test ) . and . & & exists ( join_path ( root , \"test\" , \"main.f90\" ))) then allocate ( package % test ( 1 )) call default_test ( package % test ( 1 ), package % name ) endif if (. not .( allocated ( package % library ) & & . or . allocated ( package % executable ) & & . or . allocated ( package % example ) & & . or . allocated ( package % test ))) then call fatal_error ( error , \"Neither library nor executable found, there is nothing to do\" ) return end if end subroutine package_defaults end module fpm_manifest","tags":"","loc":"sourcefile/manifest.f90.html"},{"title":"package.f90 – Fortran-lang/fpm","text":"Source Code !> Define the package data containing the meta data from the configuration file. !> !> The package data defines a Fortran type corresponding to the respective !> TOML document, after creating it from a package file no more interaction !> with the TOML document is required. !> !> Every configuration type provides it custom constructor (prefixed with `new_`) !> and knows how to deserialize itself from a TOML document. !> To ensure we find no untracked content in the package file all keywords are !> checked and possible entries have to be explicitly allowed in the `check` !> function. !> If entries are mutally exclusive or interdependent inside the current table !> the `check` function is required to enforce this schema on the data structure. !> !> The package file root allows the following keywords !> !>```toml !>name = \"string\" !>version = \"string\" !>license = \"string\" !>author = \"string\" !>maintainer = \"string\" !>copyright = \"string\" !>[library] !>[dependencies] !>[dev-dependencies] !>[profiles] !>[build] !>[install] !>[fortran] !>[[ executable ]] !>[[ example ]] !>[[ test ]] !>[extra] !>``` module fpm_manifest_package use fpm_manifest_build , only : build_config_t , new_build_config use fpm_manifest_dependency , only : dependency_config_t , new_dependencies use fpm_manifest_profile , only : profile_config_t , new_profiles , get_default_profiles use fpm_manifest_example , only : example_config_t , new_example use fpm_manifest_executable , only : executable_config_t , new_executable use fpm_manifest_fortran , only : fortran_config_t , new_fortran_config use fpm_manifest_library , only : library_config_t , new_library use fpm_manifest_install , only : install_config_t , new_install_config use fpm_manifest_test , only : test_config_t , new_test use fpm_manifest_preprocess , only : preprocess_config_t , new_preprocessors use fpm_manifest_metapackages , only : metapackage_config_t , new_meta_config use fpm_filesystem , only : exists , getline , join_path use fpm_error , only : error_t , fatal_error , syntax_error , bad_name_error use fpm_toml , only : toml_table , toml_array , toml_key , toml_stat , get_value , len , & serializable_t , set_value , set_string , set_list , add_table use fpm_versioning , only : version_t , new_version implicit none private public :: package_config_t , new_package interface unique_programs module procedure :: unique_programs1 module procedure :: unique_programs2 end interface unique_programs !> Package meta data type , extends ( serializable_t ) :: package_config_t !> Name of the package character ( len = :), allocatable :: name !> Package version type ( version_t ) :: version !> Build configuration data type ( build_config_t ) :: build !> Metapackage data type ( metapackage_config_t ) :: meta !> Installation configuration data type ( install_config_t ) :: install !> Fortran meta data type ( fortran_config_t ) :: fortran !> License meta data character ( len = :), allocatable :: license !> Author meta data character ( len = :), allocatable :: author !> Maintainer meta data character ( len = :), allocatable :: maintainer !> Copyright meta data character ( len = :), allocatable :: copyright !> Library meta data type ( library_config_t ), allocatable :: library !> Executable meta data type ( executable_config_t ), allocatable :: executable (:) !> Dependency meta data type ( dependency_config_t ), allocatable :: dependency (:) !> Development dependency meta data type ( dependency_config_t ), allocatable :: dev_dependency (:) !> Profiles meta data type ( profile_config_t ), allocatable :: profiles (:) !> Example meta data type ( example_config_t ), allocatable :: example (:) !> Test meta data type ( test_config_t ), allocatable :: test (:) !> Preprocess meta data type ( preprocess_config_t ), allocatable :: preprocess (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => manifest_is_same procedure :: dump_to_toml procedure :: load_from_toml end type package_config_t character ( len =* ), parameter , private :: class_name = 'package_config_t' contains !> Construct a new package configuration from a TOML data structure subroutine new_package ( self , table , root , error ) !> Instance of the package configuration type ( package_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Root directory of the manifest character ( len =* ), intent ( in ), optional :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error ! Backspace (8), tabulator (9), newline (10), formfeed (12) and carriage ! return (13) are invalid in package names character ( len =* ), parameter :: invalid_chars = & achar ( 8 ) // achar ( 9 ) // achar ( 10 ) // achar ( 12 ) // achar ( 13 ) type ( toml_table ), pointer :: child , node type ( toml_array ), pointer :: children character ( len = :), allocatable :: version , version_file integer :: ii , nn , stat , io call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve package name\" ) return end if if ( bad_name_error ( error , 'package' , self % name )) then return endif call get_value ( table , \"license\" , self % license ) call get_value ( table , \"author\" , self % author ) call get_value ( table , \"maintainer\" , self % maintainer ) call get_value ( table , \"copyright\" , self % copyright ) if ( len ( self % name ) <= 0 ) then call syntax_error ( error , \"Package name must be a non-empty string\" ) return end if ii = scan ( self % name , invalid_chars ) if ( ii > 0 ) then call syntax_error ( error , \"Package name contains invalid characters\" ) return end if call get_value ( table , \"build\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for build entry, must be a table\" ) return end if call new_build_config ( self % build , child , self % name , error ) if ( allocated ( error )) return call get_value ( table , \"install\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for install entry, must be a table\" ) return end if call new_install_config ( self % install , child , error ) if ( allocated ( error )) return call get_value ( table , \"fortran\" , child , requested = . true ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Type mismatch for fortran entry, must be a table\" ) return end if call new_fortran_config ( self % fortran , child , error ) if ( allocated ( error )) return call get_value ( table , \"version\" , version , \"0\" ) call new_version ( self % version , version , error ) if ( allocated ( error ) . and . present ( root )) then version_file = join_path ( root , version ) if ( exists ( version_file )) then deallocate ( error ) open ( file = version_file , newunit = io , iostat = stat ) if ( stat == 0 ) then call getline ( io , version , iostat = stat ) end if if ( stat == 0 ) then close ( io , iostat = stat ) end if if ( stat == 0 ) then call new_version ( self % version , version , error ) else call fatal_error ( error , \"Reading version number from file '\" & & // version_file // \"' failed\" ) end if end if end if if ( allocated ( error )) return call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , root , self % meta , error ) if ( allocated ( error )) return end if call get_value ( table , \"dev-dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dev_dependency , child , root , error = error ) if ( allocated ( error )) return end if call get_value ( table , \"library\" , child , requested = . false .) if ( associated ( child )) then allocate ( self % library ) call new_library ( self % library , child , error ) if ( allocated ( error )) return end if call get_value ( table , \"profiles\" , child , requested = . false .) if ( associated ( child )) then call new_profiles ( self % profiles , child , error ) if ( allocated ( error )) return else self % profiles = get_default_profiles ( error ) if ( allocated ( error )) return end if call get_value ( table , \"executable\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % executable ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve executable from array entry\" ) exit end if call new_executable ( self % executable ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % executable , error ) if ( allocated ( error )) return end if call get_value ( table , \"example\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % example ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve example from array entry\" ) exit end if call new_example ( self % example ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % example , error ) if ( allocated ( error )) return if ( allocated ( self % executable )) then call unique_programs ( self % executable , self % example , error ) if ( allocated ( error )) return end if end if call get_value ( table , \"test\" , children , requested = . false .) if ( associated ( children )) then nn = len ( children ) allocate ( self % test ( nn )) do ii = 1 , nn call get_value ( children , ii , node , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Could not retrieve test from array entry\" ) exit end if call new_test ( self % test ( ii ), node , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return call unique_programs ( self % test , error ) if ( allocated ( error )) return end if call get_value ( table , \"preprocess\" , child , requested = . false .) if ( associated ( child )) then call new_preprocessors ( self % preprocess , child , error ) if ( allocated ( error )) return end if end subroutine new_package !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) logical :: name_present integer :: ikey name_present = . false . call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Package file is empty\" ) return end if do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in package file\" ) exit case ( \"name\" ) name_present = . true . case ( \"version\" , \"license\" , \"author\" , \"maintainer\" , \"copyright\" , & & \"description\" , \"keywords\" , \"categories\" , \"homepage\" , \"build\" , & & \"dependencies\" , \"dev-dependencies\" , \"profiles\" , \"test\" , \"executable\" , & & \"example\" , \"library\" , \"install\" , \"extra\" , \"preprocess\" , \"fortran\" ) continue end select end do if ( allocated ( error )) return if (. not . name_present ) then call syntax_error ( error , \"Package name is not provided, please add a name entry\" ) end if end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the package configuration class ( package_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ii character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' , & & fmti = '(\"#\", 1x, a, t30, i0)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Package\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if call self % build % info ( unit , pr - 1 ) call self % install % info ( unit , pr - 1 ) if ( allocated ( self % library )) then write ( unit , fmt ) \"- target\" , \"archive\" call self % library % info ( unit , pr - 1 ) end if if ( allocated ( self % executable )) then if ( size ( self % executable ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- executables\" , size ( self % executable ) end if do ii = 1 , size ( self % executable ) call self % executable ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % dependency )) then if ( size ( self % dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- dependencies\" , size ( self % dependency ) end if do ii = 1 , size ( self % dependency ) call self % dependency ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % example )) then if ( size ( self % example ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- examples\" , size ( self % example ) end if do ii = 1 , size ( self % example ) call self % example ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % test )) then if ( size ( self % test ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- tests\" , size ( self % test ) end if do ii = 1 , size ( self % test ) call self % test ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % dev_dependency )) then if ( size ( self % dev_dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- development deps.\" , size ( self % dev_dependency ) end if do ii = 1 , size ( self % dev_dependency ) call self % dev_dependency ( ii )% info ( unit , pr - 1 ) end do end if if ( allocated ( self % profiles )) then if ( size ( self % profiles ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- profiles\" , size ( self % profiles ) end if do ii = 1 , size ( self % profiles ) call self % profiles ( ii )% info ( unit , pr - 1 ) end do end if end subroutine info !> Check whether or not the names in a set of executables are unique subroutine unique_programs1 ( executable , error ) !> Array of executables class ( executable_config_t ), intent ( in ) :: executable (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j do i = 1 , size ( executable ) do j = 1 , i - 1 if ( executable ( i )% name == executable ( j )% name ) then call fatal_error ( error , \"The program named '\" // & executable ( j )% name // \"' is duplicated. \" // & \"Unique program names are required.\" ) exit end if end do end do if ( allocated ( error )) return end subroutine unique_programs1 !> Check whether or not the names in a set of executables are unique subroutine unique_programs2 ( executable_i , executable_j , error ) !> Array of executables class ( executable_config_t ), intent ( in ) :: executable_i (:) !> Array of executables class ( executable_config_t ), intent ( in ) :: executable_j (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j do i = 1 , size ( executable_i ) do j = 1 , size ( executable_j ) if ( executable_i ( i )% name == executable_j ( j )% name ) then call fatal_error ( error , \"The program named '\" // & executable_j ( j )% name // \"' is duplicated. \" // & \"Unique program names are required.\" ) exit end if end do end do if ( allocated ( error )) return end subroutine unique_programs2 logical function manifest_is_same ( this , that ) class ( package_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii manifest_is_same = . false . select type ( other => that ) type is ( package_config_t ) if (. not . this % name == other % name ) return if (. not . this % version == other % version ) return if (. not . this % build == other % build ) return if (. not . this % install == other % install ) return if (. not . this % fortran == other % fortran ) return if (. not . this % license == other % license ) return if (. not . this % author == other % author ) return if (. not . this % maintainer == other % maintainer ) return if (. not . this % copyright == other % copyright ) return if ( allocated ( this % library ). neqv . allocated ( other % library )) return if ( allocated ( this % library )) then if (. not . this % library == other % library ) return endif if ( allocated ( this % executable ). neqv . allocated ( other % executable )) return if ( allocated ( this % executable )) then if (. not . size ( this % executable ) == size ( other % executable )) return do ii = 1 , size ( this % executable ) if (. not . this % executable ( ii ) == other % executable ( ii )) return end do end if if ( allocated ( this % dependency ). neqv . allocated ( other % dependency )) return if ( allocated ( this % dependency )) then if (. not . size ( this % dependency ) == size ( other % dependency )) return do ii = 1 , size ( this % dependency ) if (. not . this % dependency ( ii ) == other % dependency ( ii )) return end do end if if ( allocated ( this % dev_dependency ). neqv . allocated ( other % dev_dependency )) return if ( allocated ( this % dev_dependency )) then if (. not . size ( this % dev_dependency ) == size ( other % dev_dependency )) return do ii = 1 , size ( this % dev_dependency ) if (. not . this % dev_dependency ( ii ) == other % dev_dependency ( ii )) return end do end if if ( allocated ( this % profiles ). neqv . allocated ( other % profiles )) return if ( allocated ( this % profiles )) then if (. not . size ( this % profiles ) == size ( other % profiles )) return do ii = 1 , size ( this % profiles ) if (. not . this % profiles ( ii ) == other % profiles ( ii )) return end do end if if ( allocated ( this % example ). neqv . allocated ( other % example )) return if ( allocated ( this % example )) then if (. not . size ( this % example ) == size ( other % example )) return do ii = 1 , size ( this % example ) if (. not . this % example ( ii ) == other % example ( ii )) return end do end if if ( allocated ( this % preprocess ). neqv . allocated ( other % preprocess )) return if ( allocated ( this % preprocess )) then if (. not . size ( this % preprocess ) == size ( other % preprocess )) return do ii = 1 , size ( this % preprocess ) if (. not . this % preprocess ( ii ) == other % preprocess ( ii )) return end do end if if ( allocated ( this % test ). neqv . allocated ( other % test )) return if ( allocated ( this % test )) then if (. not . size ( this % test ) == size ( other % test )) return do ii = 1 , size ( this % test ) if (. not . this % test ( ii ) == other % test ( ii )) return end do end if class default ! Not the same type return end select !> All checks passed! manifest_is_same = . true . end function manifest_is_same !> Dump manifest to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( package_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii type ( toml_table ), pointer :: ptr , ptr_pkg character ( 30 ) :: unnamed character ( 128 ) :: profile_name call set_string ( table , \"name\" , self % name , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"version\" , self % version % s (), error , class_name ) if ( allocated ( error )) return call set_string ( table , \"license\" , self % license , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"author\" , self % author , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"maintainer\" , self % maintainer , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"copyright\" , self % copyright , error , class_name ) if ( allocated ( error )) return call add_table ( table , \"build\" , ptr , error , class_name ) if ( allocated ( error )) return call self % build % dump_to_toml ( ptr , error ) if ( allocated ( error )) return call add_table ( table , \"fortran\" , ptr , error , class_name ) if ( allocated ( error )) return call self % fortran % dump_to_toml ( ptr , error ) if ( allocated ( error )) return call add_table ( table , \"install\" , ptr , error , class_name ) if ( allocated ( error )) return call self % install % dump_to_toml ( ptr , error ) if ( allocated ( error )) return if ( allocated ( self % library )) then call add_table ( table , \"library\" , ptr , error , class_name ) if ( allocated ( error )) return call self % library % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end if if ( allocated ( self % executable )) then call add_table ( table , \"executable\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'executable' table \" ) return end if do ii = 1 , size ( self % executable ) associate ( pkg => self % executable ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'EXECUTABLE' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(executable)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(executable)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % dependency )) then call add_table ( table , \"dependencies\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'dependencies' table \" ) return end if do ii = 1 , size ( self % dependency ) associate ( pkg => self % dependency ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'DEPENDENCY' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(dependencies)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(dependencies)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % dev_dependency )) then call add_table ( table , \"dev-dependencies\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'dev-dependencies' table \" ) return end if do ii = 1 , size ( self % dev_dependency ) associate ( pkg => self % dev_dependency ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'DEV-DEPENDENCY' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(dev-dependencies)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(dev-dependencies)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % profiles )) then call add_table ( table , \"profiles\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'profiles' table \" ) return end if do ii = 1 , size ( self % profiles ) associate ( pkg => self % profiles ( ii )) !> Duplicate profile names are possible, as multiple profiles are possible with the !> same name, same compiler, etc. So, use a unique name here write ( profile_name , 2 ) ii call add_table ( ptr_pkg , trim ( profile_name ), ptr , error , class_name // '(profiles)' ) if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % example )) then call add_table ( table , \"example\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'example' table \" ) return end if do ii = 1 , size ( self % example ) associate ( pkg => self % example ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'EXAMPLE' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(example)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(example)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % test )) then call add_table ( table , \"test\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'test' table \" ) return end if do ii = 1 , size ( self % test ) associate ( pkg => self % test ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'TEST' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(test)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(test)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if if ( allocated ( self % preprocess )) then call add_table ( table , \"preprocess\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , class_name // \" cannot create 'preprocess' table \" ) return end if do ii = 1 , size ( self % preprocess ) associate ( pkg => self % preprocess ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) 'PREPROCESS' , ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , class_name // '(preprocess)' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , class_name // '(preprocess)' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if 1 format ( 'UNNAMED_' , a , '_' , i0 ) 2 format ( 'PROFILE_' , i0 ) end subroutine dump_to_toml !> Read manifest from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( package_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: keys (:), pkg_keys (:) integer :: ierr , ii , jj character ( len = :), allocatable :: flag type ( toml_table ), pointer :: ptr , ptr_pkg call table % get_keys ( keys ) call get_value ( table , \"name\" , self % name ) call get_value ( table , \"license\" , self % license ) call get_value ( table , \"author\" , self % author ) call get_value ( table , \"maintainer\" , self % maintainer ) call get_value ( table , \"copyright\" , self % copyright ) call get_value ( table , \"version\" , flag ) call new_version ( self % version , flag , error ) if ( allocated ( error )) then error % message = class_name // ': version error from TOML table - ' // error % message return endif if ( allocated ( self % library )) deallocate ( self % library ) if ( allocated ( self % executable )) deallocate ( self % executable ) if ( allocated ( self % dependency )) deallocate ( self % dependency ) if ( allocated ( self % dev_dependency )) deallocate ( self % dev_dependency ) if ( allocated ( self % profiles )) deallocate ( self % profiles ) if ( allocated ( self % example )) deallocate ( self % example ) if ( allocated ( self % test )) deallocate ( self % test ) if ( allocated ( self % preprocess )) deallocate ( self % preprocess ) sub_deps : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"build\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving ' // keys ( ii )% key // ' table' ) return end if call self % build % load_from_toml ( ptr , error ) if ( allocated ( error )) return case ( \"install\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving ' // keys ( ii )% key // ' table' ) return end if call self % install % load_from_toml ( ptr , error ) case ( \"fortran\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving ' // keys ( ii )% key // ' table' ) return end if call self % fortran % load_from_toml ( ptr , error ) case ( \"library\" ) allocate ( self % library ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving ' // keys ( ii )% key // ' table' ) return end if call self % library % load_from_toml ( ptr , error ) case ( \"executable\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving executable table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % executable ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % executable ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"dependencies\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving dependency table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % dependency ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % dependency ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"dev-dependencies\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving dev-dependencies table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % dev_dependency ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % dev_dependency ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"profiles\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving profiles table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % profiles ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % profiles ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"example\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving example table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % example ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % example ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"test\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving test table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % test ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % test ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case ( \"preprocess\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , class_name // ': error retrieving preprocess table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % preprocess ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % preprocess ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case default cycle sub_deps end select end do sub_deps end subroutine load_from_toml end module fpm_manifest_package","tags":"","loc":"sourcefile/package.f90.html"},{"title":"toml.f90 – Fortran-lang/fpm","text":"Source Code !># Interface to TOML processing library !> !> This module acts as a proxy to the `toml-f` public Fortran API and allows !> to selectively expose components from the library to `fpm`. !> The interaction with `toml-f` data types outside of this module should be !> limited to tables, arrays and key-lists, most of the necessary interactions !> are implemented in the building interface with the `get_value` and `set_value` !> procedures. !> !> This module allows to implement features necessary for `fpm`, which are !> not yet available in upstream `toml-f`. !> !> For more details on the library used see the !> [TOML-Fortran](https://toml-f.github.io/toml-f) developer pages. module fpm_toml use fpm_error , only : error_t , fatal_error , file_not_found_error use fpm_strings , only : string_t , str_ends_with , lower use tomlf , only : toml_table , toml_array , toml_key , toml_stat , get_value , & & set_value , toml_parse , toml_error , new_table , add_table , add_array , & & toml_serialize , len , toml_load , toml_value use tomlf_de_parser , only : parse use jonquil , only : json_serialize , json_error , json_value , json_object , json_load , & cast_to_object use iso_fortran_env , only : int64 implicit none private public :: read_package_file , toml_table , toml_array , toml_key , toml_stat , & get_value , set_value , get_list , new_table , add_table , add_array , len , & toml_error , toml_serialize , toml_load , check_keys , set_list , set_string , & name_is_json !> An abstract interface for any fpm class that should be fully serializable to/from TOML/JSON type , abstract , public :: serializable_t contains !> Dump to TOML table, unit, file procedure ( to_toml ), deferred :: dump_to_toml procedure , non_overridable , private :: dump_to_file procedure , non_overridable , private :: dump_to_unit generic :: dump => dump_to_toml , dump_to_file , dump_to_unit !> Load from TOML table, unit, file procedure ( from_toml ), deferred :: load_from_toml procedure , non_overridable , private :: load_from_file procedure , non_overridable , private :: load_from_unit generic :: load => load_from_toml , load_from_file , load_from_unit !> Serializable entities need a way to check that they're equal procedure ( is_equal ), deferred :: serializable_is_same generic :: operator ( == ) => serializable_is_same !> Test load/write roundtrip procedure , non_overridable :: test_serialization end type serializable_t !> add_table: fpm interface interface add_table module procedure add_table_fpm end interface add_table !> set_value: fpm interface interface set_value module procedure set_logical module procedure set_integer module procedure set_integer_64 end interface set_value interface set_string module procedure set_character module procedure set_string_type end interface set_string !> get_value: fpm interface interface get_value module procedure get_logical module procedure get_integer module procedure get_integer_64 end interface get_value abstract interface !> Write object to TOML datastructure subroutine to_toml ( self , table , error ) import serializable_t , toml_table , error_t implicit none !> Instance of the serializable object class ( serializable_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error end subroutine to_toml !> Read dependency tree from TOML data structure subroutine from_toml ( self , table , error ) import serializable_t , toml_table , error_t implicit none !> Instance of the serializable object class ( serializable_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error end subroutine from_toml !> Compare two serializable objects logical function is_equal ( this , that ) import serializable_t class ( serializable_t ), intent ( in ) :: this , that end function is_equal end interface contains !> Test serialization of a serializable object subroutine test_serialization ( self , message , error ) class ( serializable_t ), intent ( inout ) :: self character ( len =* ), intent ( in ) :: message type ( error_t ), allocatable , intent ( out ) :: error integer :: iunit , ii class ( serializable_t ), allocatable :: copy character ( len = 4 ), parameter :: formats ( 2 ) = [ 'TOML' , 'JSON' ] all_formats : do ii = 1 , 2 open ( newunit = iunit , form = 'formatted' , action = 'readwrite' , status = 'scratch' ) !> Dump to scratch file call self % dump ( iunit , error , json = ii == 2 ) if ( allocated ( error )) then error % message = formats ( ii ) // ': ' // error % message return endif !> Load from scratch file rewind ( iunit ) allocate ( copy , mold = self ) call copy % load ( iunit , error , json = ii == 2 ) if ( allocated ( error )) then error % message = formats ( ii ) // ': ' // error % message return endif close ( iunit ) !> Check same if (. not .( self == copy )) then call fatal_error ( error , 'serializable object failed ' // formats ( ii ) // & ' write/reread test: ' // trim ( message )) return end if deallocate ( copy ) end do all_formats end subroutine test_serialization !> Write serializable object to a formatted Fortran unit subroutine dump_to_unit ( self , unit , error , json ) !> Instance of the dependency tree class ( serializable_t ), intent ( inout ) :: self !> Formatted unit integer , intent ( in ) :: unit !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional JSON format requested? logical , optional , intent ( in ) :: json type ( toml_table ) :: table logical :: is_json is_json = . false .; if ( present ( json )) is_json = json table = toml_table () call self % dump ( table , error ) if ( is_json ) then ! !> Deactivate JSON serialization for now ! call fatal_error(error, 'JSON serialization option is not yet available') ! return write ( unit , '(a)' ) json_serialize ( table ) else write ( unit , '(a)' ) toml_serialize ( table ) end if call table % destroy () end subroutine dump_to_unit !> Write serializable object to file subroutine dump_to_file ( self , file , error , json ) !> Instance of the dependency tree class ( serializable_t ), intent ( inout ) :: self !> File name character ( len =* ), intent ( in ) :: file !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional JSON format logical , optional , intent ( in ) :: json integer :: unit open ( file = file , newunit = unit ) call self % dump ( unit , error , json ) close ( unit ) if ( allocated ( error )) return end subroutine dump_to_file !> Read dependency tree from file subroutine load_from_file ( self , file , error , json ) !> Instance of the dependency tree class ( serializable_t ), intent ( inout ) :: self !> File name character ( len =* ), intent ( in ) :: file !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional JSON format logical , optional , intent ( in ) :: json integer :: unit logical :: exist inquire ( file = file , exist = exist ) if (. not . exist ) return open ( file = file , newunit = unit ) call self % load ( unit , error , json ) close ( unit ) end subroutine load_from_file !> Read dependency tree from file subroutine load_from_unit ( self , unit , error , json ) !> Instance of the dependency tree class ( serializable_t ), intent ( inout ) :: self !> File name integer , intent ( in ) :: unit !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional JSON format logical , optional , intent ( in ) :: json type ( toml_error ), allocatable :: local_error type ( toml_table ), allocatable :: table type ( toml_table ), pointer :: jtable class ( toml_value ), allocatable :: object logical :: is_json is_json = . false .; if ( present ( json )) is_json = json if ( is_json ) then !> init JSON interpreter call json_load ( object , unit , error = local_error ) if ( allocated ( local_error )) then allocate ( error ) call move_alloc ( local_error % message , error % message ) return end if jtable => cast_to_object ( object ) if (. not . associated ( jtable )) then call fatal_error ( error , 'cannot initialize JSON table ' ) return end if !> Read object from TOML table call self % load ( jtable , error ) else !> use default TOML parser call toml_load ( table , unit , error = local_error ) if ( allocated ( local_error )) then allocate ( error ) call move_alloc ( local_error % message , error % message ) return end if !> Read object from TOML table call self % load ( table , error ) endif if ( allocated ( error )) return end subroutine load_from_unit !> Process the configuration file to a TOML data structure subroutine read_package_file ( table , manifest , error ) !> TOML data structure type ( toml_table ), allocatable , intent ( out ) :: table !> Name of the package configuration file character ( len =* ), intent ( in ) :: manifest !> Error status of the operation type ( error_t ), allocatable , intent ( out ) :: error type ( toml_error ), allocatable :: parse_error integer :: unit logical :: exist inquire ( file = manifest , exist = exist ) if (. not . exist ) then call file_not_found_error ( error , manifest ) return end if open ( file = manifest , newunit = unit ) call toml_load ( table , unit , error = parse_error ) close ( unit ) if ( allocated ( parse_error )) then allocate ( error ) call move_alloc ( parse_error % message , error % message ) return end if end subroutine read_package_file subroutine get_list ( table , key , list , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Key to read from character ( len =* ), intent ( in ) :: key !> List of strings to read type ( string_t ), allocatable , intent ( out ) :: list (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , ilist , nlist type ( toml_array ), pointer :: children character ( len = :), allocatable :: str if (. not . table % has_key ( key )) return call get_value ( table , key , children , requested = . false .) if ( associated ( children )) then nlist = len ( children ) allocate ( list ( nlist )) do ilist = 1 , nlist call get_value ( children , ilist , str , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Entry in \" // key // \" field cannot be read\" ) exit end if call move_alloc ( str , list ( ilist )% s ) end do if ( allocated ( error )) return else call get_value ( table , key , str , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Entry in \" // key // \" field cannot be read\" ) return end if if ( allocated ( str )) then allocate ( list ( 1 )) call move_alloc ( str , list ( 1 )% s ) end if end if end subroutine get_list ! Set string array subroutine set_list ( table , key , list , error ) !> Instance of the string array type ( string_t ), allocatable , intent ( in ) :: list (:) !> Key to save to character ( len =* ), intent ( in ) :: key !> Instance of the toml table type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: stat , ilist type ( toml_array ), pointer :: children character ( len = :), allocatable :: str !> Set no key if array is not present if (. not . allocated ( list )) return !> Check the key is not empty if ( len_trim ( key ) <= 0 ) then call fatal_error ( error , 'key is empty dumping string array to TOML table' ) return end if if ( size ( list ) /= 1 ) then ! includes empty list case !> String array call add_array ( table , key , children , stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Cannot set array table in \" // key // \" field\" ) return end if do ilist = 1 , size ( list ) call set_value ( children , ilist , list ( ilist )% s , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Cannot store array entry in \" // key // \" field\" ) return end if end do else ! Single value: set string call set_value ( table , key , list ( 1 )% s , stat = stat ) if ( stat /= toml_stat % success ) & call fatal_error ( error , \"Cannot store entry in \" // key // \" field\" ) return end if end subroutine set_list !> Function wrapper to set a character(len=:), allocatable variable to a toml table subroutine set_character ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys to check. character ( len =* ), intent ( in ) :: key !> The character variable character ( len =* ), optional , intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr !> Check the key is not empty if ( len_trim ( key ) <= 0 ) then call fatal_error ( error , 'key is empty setting character string to TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if if ( present ( var )) then call set_value ( table , key , var , ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot set character key <' // key // '> in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if endif end subroutine set_character !> Function wrapper to set a logical variable to a toml table, returning an fpm error subroutine set_logical ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable logical , intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call set_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot set logical key <' // key // '> in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine set_logical !> Function wrapper to set a default integer variable to a toml table, returning an fpm error subroutine set_integer ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable integer , intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call set_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot set integer key <' // key // '> in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine set_integer !> Function wrapper to set a default integer variable to a toml table, returning an fpm error subroutine set_integer_64 ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable integer ( int64 ), intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call set_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot set integer(int64) key <' // key // '> in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine set_integer_64 !> Function wrapper to set a character(len=:), allocatable variable to a toml table subroutine set_string_type ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys to check. character ( len =* ), intent ( in ) :: key !> The character variable type ( string_t ), intent ( in ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt call set_character ( table , key , var % s , error , whereAt ) end subroutine set_string_type !> Function wrapper to add a toml table and return an fpm error subroutine add_table_fpm ( table , key , ptr , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Table key character ( len =* ), intent ( in ) :: key !> The character variable type ( toml_table ), pointer , intent ( out ) :: ptr !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr !> Nullify pointer nullify ( ptr ) call add_table ( table , key , ptr , ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot add <' // key // '> table in TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine add_table_fpm !> Function wrapper to get a logical variable from a toml table, returning an fpm error subroutine get_logical ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable logical , intent ( inout ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call get_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot get logical key <' // key // '> from TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine get_logical !> Function wrapper to get a default integer variable from a toml table, returning an fpm error subroutine get_integer ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable integer , intent ( inout ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call get_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot get integer key <' // key // '> from TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine get_integer !> Function wrapper to get a integer(int64) variable from a toml table, returning an fpm error subroutine get_integer_64 ( table , key , var , error , whereAt ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> The key character ( len =* ), intent ( in ) :: key !> The variable integer ( int64 ), intent ( inout ) :: var !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Optional description character ( len =* ), intent ( in ), optional :: whereAt integer :: ierr call get_value ( table , key , var , stat = ierr ) if ( ierr /= toml_stat % success ) then call fatal_error ( error , 'cannot get integer(int64) key <' // key // '> from TOML table' ) if ( present ( whereAt )) error % message = whereAt // ': ' // error % message return end if end subroutine get_integer_64 !> Check if table contains only keys that are part of the list. If a key is !> found that is not part of the list, an error is allocated. subroutine check_keys ( table , valid_keys , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys to check. character ( len =* ), intent ( in ) :: valid_keys (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: keys (:) type ( toml_table ), pointer :: child character (:), allocatable :: name , value , valid_keys_string integer :: ikey , ivalid call table % get_key ( name ) call table % get_keys ( keys ) do ikey = 1 , size ( keys ) if (. not . any ( keys ( ikey )% key == valid_keys )) then ! Generate error message valid_keys_string = new_line ( 'a' ) // new_line ( 'a' ) do ivalid = 1 , size ( valid_keys ) valid_keys_string = valid_keys_string // trim ( valid_keys ( ivalid )) // new_line ( 'a' ) end do allocate ( error ) error % message = \"Key '\" // keys ( ikey )% key // \"' not allowed in the '\" // & & name // \"' table.\" // new_line ( 'a' ) // new_line ( 'a' ) // 'Valid keys: ' // valid_keys_string return end if ! Check if value can be mapped or else (wrong type) show error message with the error location. ! Right now, it can only be mapped to a string or to a child node, but this can be extended in the future. call get_value ( table , keys ( ikey )% key , value ) if (. not . allocated ( value )) then ! If value is not a string, check if it is a child node call get_value ( table , keys ( ikey )% key , child ) if (. not . associated ( child )) then allocate ( error ) error % message = \"'\" // name // \"' has an invalid '\" // keys ( ikey )% key // \"' entry.\" return endif end if end do end subroutine check_keys !> Choose between JSON or TOML based on a file name logical function name_is_json ( filename ) character ( * ), intent ( in ) :: filename character ( * ), parameter :: json_identifier = \".json\" name_is_json = . false . if ( len_trim ( filename ) < len ( json_identifier )) return name_is_json = str_ends_with ( lower ( filename ), json_identifier ) end function name_is_json end module fpm_toml","tags":"","loc":"sourcefile/toml.f90.html"},{"title":"install.f90 – Fortran-lang/fpm","text":"Source Code module fpm_cmd_install use , intrinsic :: iso_fortran_env , only : output_unit use fpm , only : build_model use fpm_backend , only : build_package use fpm_command_line , only : fpm_install_settings use fpm_error , only : error_t , fatal_error , fpm_stop use fpm_filesystem , only : join_path , list_files use fpm_installer , only : installer_t , new_installer use fpm_manifest , only : package_config_t , get_package_data use fpm_model , only : fpm_model_t , FPM_SCOPE_APP use fpm_targets , only : targets_from_sources , build_target_t , & build_target_ptr , FPM_TARGET_EXECUTABLE , & filter_library_targets , filter_executable_targets , filter_modules use fpm_strings , only : string_t , resize implicit none private public :: cmd_install contains !> Entry point for the fpm-install subcommand subroutine cmd_install ( settings ) !> Representation of the command line settings type ( fpm_install_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( error_t ), allocatable :: error type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( installer_t ) :: installer type ( string_t ), allocatable :: list (:) logical :: installable integer :: ntargets call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) call build_model ( model , settings , package , error ) call handle_error ( error ) call targets_from_sources ( targets , model , settings % prune , error ) call handle_error ( error ) call install_info ( output_unit , settings % list , targets , ntargets ) if ( settings % list ) return installable = ( allocated ( package % library ) . and . package % install % library ) & . or . allocated ( package % executable ) . or . ntargets > 0 if (. not . installable ) then call fatal_error ( error , \"Project does not contain any installable targets\" ) call handle_error ( error ) end if if (. not . settings % no_rebuild ) then call build_package ( targets , model , verbose = settings % verbose ) end if call new_installer ( installer , prefix = settings % prefix , & bindir = settings % bindir , libdir = settings % libdir , & includedir = settings % includedir , & verbosity = merge ( 2 , 1 , settings % verbose )) if ( allocated ( package % library ) . and . package % install % library ) then call filter_library_targets ( targets , list ) if ( size ( list ) > 0 ) then call installer % install_library ( list ( 1 )% s , error ) call handle_error ( error ) call install_module_files ( installer , targets , error ) call handle_error ( error ) end if end if if ( allocated ( package % executable ) . or . ntargets > 0 ) then call install_executables ( installer , targets , error ) call handle_error ( error ) end if end subroutine cmd_install subroutine install_info ( unit , verbose , targets , ntargets ) integer , intent ( in ) :: unit logical , intent ( in ) :: verbose type ( build_target_ptr ), intent ( in ) :: targets (:) integer , intent ( out ) :: ntargets integer :: ii type ( string_t ), allocatable :: install_target (:), temp (:) allocate ( install_target ( 0 )) call filter_library_targets ( targets , temp ) install_target = [ install_target , temp ] call filter_executable_targets ( targets , FPM_SCOPE_APP , temp ) install_target = [ install_target , temp ] ntargets = size ( install_target ) if ( verbose ) then write ( unit , '(\"#\", *(1x, g0))' ) & \"total number of installable targets:\" , ntargets do ii = 1 , ntargets write ( unit , '(\"-\", *(1x, g0))' ) install_target ( ii )% s end do endif end subroutine install_info subroutine install_module_files ( installer , targets , error ) type ( installer_t ), intent ( inout ) :: installer type ( build_target_ptr ), intent ( in ) :: targets (:) type ( error_t ), allocatable , intent ( out ) :: error type ( string_t ), allocatable :: modules (:) integer :: ii call filter_modules ( targets , modules ) do ii = 1 , size ( modules ) call installer % install_header ( modules ( ii )% s // \".mod\" , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return end subroutine install_module_files subroutine install_executables ( installer , targets , error ) type ( installer_t ), intent ( inout ) :: installer type ( build_target_ptr ), intent ( in ) :: targets (:) type ( error_t ), allocatable , intent ( out ) :: error integer :: ii do ii = 1 , size ( targets ) if ( targets ( ii )% ptr % is_executable_target ( FPM_SCOPE_APP )) then call installer % install_executable ( targets ( ii )% ptr % output_file , error ) if ( allocated ( error )) exit end if end do if ( allocated ( error )) return end subroutine install_executables subroutine handle_error ( error ) type ( error_t ), intent ( in ), optional :: error if ( present ( error )) then call fpm_stop ( 1 , '*cmd_install* error: ' // error % message ) end if end subroutine handle_error end module fpm_cmd_install","tags":"","loc":"sourcefile/install.f90~2.html"},{"title":"profiles.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for compiler flag profiles. !> !> A profiles table can currently have the following subtables: !> Profile names - any string, if omitted, flags are appended to all matching profiles !> Compiler - any from the following list, omitting it yields an error !> !> - \"gfortran\" !> - \"ifort\" !> - \"ifx\" !> - \"pgfortran\" !> - \"nvfortran\" !> - \"flang\" !> - \"caf\" !> - \"f95\" !> - \"lfortran\" !> - \"lfc\" !> - \"nagfor\" !> - \"crayftn\" !> - \"xlf90\" !> - \"ftn95\" !> !> OS - any from the following list, if omitted, the profile is used if and only !> if there is no profile perfectly matching the current configuration !> !> - \"linux\" !> - \"macos\" !> - \"windows\" !> - \"cygwin\" !> - \"solaris\" !> - \"freebsd\" !> - \"openbsd\" !> - \"unknown\" !> !> Each of the subtables currently supports the following fields: !>```toml !>[profiles.debug.gfortran.linux] !> flags=\"-Wall -g -Og\" !> c-flags=\"-g O1\" !> cxx-flags=\"-g O1\" !> link-time-flags=\"-xlinkopt\" !> files={\"hello_world.f90\"=\"-Wall -O3\"} !>``` !> module fpm_manifest_profile use fpm_error , only : error_t , syntax_error , fatal_error , fpm_stop use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , serializable_t , set_value , & set_string , add_table use fpm_strings , only : lower use fpm_environment , only : get_os_type , OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_WINDOWS , & OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD , OS_NAME use fpm_filesystem , only : join_path implicit none public :: profile_config_t , new_profile , new_profiles , get_default_profiles , & & info_profile , find_profile , DEFAULT_COMPILER !> Name of the default compiler character ( len =* ), parameter :: DEFAULT_COMPILER = 'gfortran' integer , parameter :: OS_ALL = - 1 character ( len = :), allocatable :: path !> Type storing file name - file scope compiler flags pairs type , extends ( serializable_t ) :: file_scope_flag !> Name of the file character ( len = :), allocatable :: file_name !> File scope flags character ( len = :), allocatable :: flags contains !> Serialization interface procedure :: serializable_is_same => file_scope_same procedure :: dump_to_toml => file_scope_dump procedure :: load_from_toml => file_scope_load end type file_scope_flag !> Configuration meta data for a profile type , extends ( serializable_t ) :: profile_config_t !> Name of the profile character ( len = :), allocatable :: profile_name !> Name of the compiler character ( len = :), allocatable :: compiler !> Value repesenting OS integer :: os_type = OS_ALL !> Fortran compiler flags character ( len = :), allocatable :: flags !> C compiler flags character ( len = :), allocatable :: c_flags !> C++ compiler flags character ( len = :), allocatable :: cxx_flags !> Link time compiler flags character ( len = :), allocatable :: link_time_flags !> File scope flags type ( file_scope_flag ), allocatable :: file_scope_flags (:) !> Is this profile one of the built-in ones? logical :: is_built_in = . false . contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => profile_same procedure :: dump_to_toml => profile_dump procedure :: load_from_toml => profile_load end type profile_config_t contains !> Construct a new profile configuration from a TOML data structure function new_profile ( profile_name , compiler , os_type , flags , c_flags , cxx_flags , & link_time_flags , file_scope_flags , is_built_in ) & & result ( profile ) !> Name of the profile character ( len =* ), intent ( in ) :: profile_name !> Name of the compiler character ( len =* ), intent ( in ) :: compiler !> Type of the OS integer , intent ( in ) :: os_type !> Fortran compiler flags character ( len =* ), optional , intent ( in ) :: flags !> C compiler flags character ( len =* ), optional , intent ( in ) :: c_flags !> C++ compiler flags character ( len =* ), optional , intent ( in ) :: cxx_flags !> Link time compiler flags character ( len =* ), optional , intent ( in ) :: link_time_flags !> File scope flags type ( file_scope_flag ), optional , intent ( in ) :: file_scope_flags (:) !> Is this profile one of the built-in ones? logical , optional , intent ( in ) :: is_built_in type ( profile_config_t ) :: profile profile % profile_name = profile_name profile % compiler = compiler profile % os_type = os_type if ( present ( flags )) then profile % flags = flags else profile % flags = \"\" end if if ( present ( c_flags )) then profile % c_flags = c_flags else profile % c_flags = \"\" end if if ( present ( cxx_flags )) then profile % cxx_flags = cxx_flags else profile % cxx_flags = \"\" end if if ( present ( link_time_flags )) then profile % link_time_flags = link_time_flags else profile % link_time_flags = \"\" end if if ( present ( file_scope_flags )) then profile % file_scope_flags = file_scope_flags end if if ( present ( is_built_in )) then profile % is_built_in = is_built_in else profile % is_built_in = . false . end if end function new_profile !> Check if compiler name is a valid compiler name subroutine validate_compiler_name ( compiler_name , is_valid ) !> Name of a compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> Boolean value of whether compiler_name is valid or not logical , intent ( out ) :: is_valid select case ( compiler_name ) case ( \"gfortran\" , \"ifort\" , \"ifx\" , \"pgfortran\" , \"nvfortran\" , \"flang\" , \"caf\" , & & \"f95\" , \"lfortran\" , \"lfc\" , \"nagfor\" , \"crayftn\" , \"xlf90\" , \"ftn95\" ) is_valid = . true . case default is_valid = . false . end select end subroutine validate_compiler_name !> Check if os_name is a valid name of a supported OS subroutine validate_os_name ( os_name , is_valid ) !> Name of an operating system character ( len = :), allocatable , intent ( in ) :: os_name !> Boolean value of whether os_name is valid or not logical , intent ( out ) :: is_valid select case ( os_name ) case ( \"linux\" , \"macos\" , \"windows\" , \"cygwin\" , \"solaris\" , \"freebsd\" , & & \"openbsd\" , \"unknown\" ) is_valid = . true . case default is_valid = . false . end select end subroutine validate_os_name !> Match os_type enum to a lowercase string with name of OS subroutine match_os_type ( os_name , os_type ) !> Name of operating system character ( len = :), allocatable , intent ( in ) :: os_name !> Enum representing type of OS integer , intent ( out ) :: os_type select case ( os_name ) case ( \"linux\" ); os_type = OS_LINUX case ( \"macos\" ); os_type = OS_MACOS case ( \"windows\" ); os_type = OS_WINDOWS case ( \"cygwin\" ); os_type = OS_CYGWIN case ( \"solaris\" ); os_type = OS_SOLARIS case ( \"freebsd\" ); os_type = OS_FREEBSD case ( \"openbsd\" ); os_type = OS_OPENBSD case ( \"all\" ); os_type = OS_ALL case default ; os_type = OS_UNKNOWN end select end subroutine match_os_type !> Match lowercase string with name of OS to os_type enum function os_type_name ( os_type ) !> Name of operating system character ( len = :), allocatable :: os_type_name !> Enum representing type of OS integer , intent ( in ) :: os_type select case ( os_type ) case ( OS_ALL ); os_type_name = \"all\" case default ; os_type_name = lower ( OS_NAME ( os_type )) end select end function os_type_name subroutine validate_profile_table ( profile_name , compiler_name , key_list , table , error , os_valid ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of keys in the table type ( toml_key ), allocatable , intent ( in ) :: key_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Was called with valid operating system logical , intent ( in ) :: os_valid character ( len = :), allocatable :: flags , c_flags , cxx_flags , link_time_flags , key_name , file_name , file_flags , err_message type ( toml_table ), pointer :: files type ( toml_key ), allocatable :: file_list (:) integer :: ikey , ifile , stat logical :: is_valid if ( size ( key_list ). ge . 1 ) then do ikey = 1 , size ( key_list ) key_name = key_list ( ikey )% key if ( key_name . eq . 'flags' ) then call get_value ( table , 'flags' , flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'c-flags' ) then call get_value ( table , 'c-flags' , c_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"c-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'cxx-flags' ) then call get_value ( table , 'cxx-flags' , cxx_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"cxx-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'link-time-flags' ) then call get_value ( table , 'link-time-flags' , link_time_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"link-time-flags has to be a key-value pair\" ) return end if else if ( key_name . eq . 'files' ) then call get_value ( table , 'files' , files , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"files has to be a table\" ) return end if call files % get_keys ( file_list ) do ifile = 1 , size ( file_list ) file_name = file_list ( ifile )% key call get_value ( files , file_name , file_flags , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"file scope flags has to be a key-value pair\" ) return end if end do else if (. not . os_valid ) then call validate_os_name ( key_name , is_valid ) err_message = \"Unexpected key \" // key_name // \" found in profile table \" // profile_name // \" \" // compiler_name // \".\" if (. not . is_valid ) call syntax_error ( error , err_message ) else err_message = \"Unexpected key \" // key_name // \" found in profile table \" // profile_name // \" \" // compiler_name // \".\" call syntax_error ( error , err_message ) end if end do end if if ( allocated ( error )) return end subroutine validate_profile_table !> Look for flags, c-flags, link-time-flags key-val pairs !> and files table in a given table and create new profiles subroutine get_flags ( profile_name , compiler_name , os_type , key_list , table , profiles , profindex , os_valid ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> OS type integer , intent ( in ) :: os_type !> List of keys in the table type ( toml_key ), allocatable , intent ( in ) :: key_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ) :: profiles (:) !> Index in the list of profiles integer , intent ( inout ) :: profindex !> Was called with valid operating system logical , intent ( in ) :: os_valid character ( len = :), allocatable :: flags , c_flags , cxx_flags , link_time_flags , key_name , file_name , file_flags , err_message type ( toml_table ), pointer :: files type ( toml_key ), allocatable :: file_list (:) type ( file_scope_flag ), allocatable :: file_scope_flags (:) integer :: ikey , ifile , stat logical :: is_valid call get_value ( table , 'flags' , flags ) call get_value ( table , 'c-flags' , c_flags ) call get_value ( table , 'cxx-flags' , cxx_flags ) call get_value ( table , 'link-time-flags' , link_time_flags ) call get_value ( table , 'files' , files ) if ( associated ( files )) then call files % get_keys ( file_list ) allocate ( file_scope_flags ( size ( file_list ))) do ifile = 1 , size ( file_list ) file_name = file_list ( ifile )% key call get_value ( files , file_name , file_flags ) associate ( cur_file => file_scope_flags ( ifile )) if (. not .( path . eq . \"\" )) file_name = join_path ( path , file_name ) cur_file % file_name = file_name cur_file % flags = file_flags end associate end do end if profiles ( profindex ) = new_profile ( profile_name , compiler_name , os_type , & & flags , c_flags , cxx_flags , link_time_flags , file_scope_flags ) profindex = profindex + 1 end subroutine get_flags !> Traverse operating system tables to obtain number of profiles subroutine traverse_oss_for_size ( profile_name , compiler_name , os_list , table , profiles_size , error ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of OSs in table with profile name and compiler name given type ( toml_key ), allocatable , intent ( in ) :: os_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Number of profiles in list of profiles integer , intent ( inout ) :: profiles_size type ( toml_key ), allocatable :: key_list (:) character ( len = :), allocatable :: os_name , l_os_name type ( toml_table ), pointer :: os_node integer :: ios , stat logical :: is_valid , key_val_added , is_key_val if ( size ( os_list ) < 1 ) return key_val_added = . false . do ios = 1 , size ( os_list ) os_name = os_list ( ios )% key call validate_os_name ( os_name , is_valid ) if ( is_valid ) then call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"os \" // os_name // \" has to be a table\" ) return end if call os_node % get_keys ( key_list ) profiles_size = profiles_size + 1 call validate_profile_table ( profile_name , compiler_name , key_list , os_node , error , . true .) else ! Not lowercase OS name l_os_name = lower ( os_name ) call validate_os_name ( l_os_name , is_valid ) if ( is_valid ) then call fatal_error ( error , '*traverse_oss*:Error: Name of the operating system must be a lowercase string.' ) end if if ( allocated ( error )) return ! Missing OS name is_key_val = . false . os_name = os_list ( ios )% key call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then is_key_val = . true . end if os_node => table if ( is_key_val . and .. not . key_val_added ) then key_val_added = . true . is_key_val = . false . profiles_size = profiles_size + 1 else if (. not . is_key_val ) then profiles_size = profiles_size + 1 end if call validate_profile_table ( profile_name , compiler_name , os_list , os_node , error , . false .) end if end do end subroutine traverse_oss_for_size !> Traverse operating system tables to obtain profiles subroutine traverse_oss ( profile_name , compiler_name , os_list , table , profiles , profindex , error ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> Name of compiler character ( len = :), allocatable , intent ( in ) :: compiler_name !> List of OSs in table with profile name and compiler name given type ( toml_key ), allocatable , intent ( in ) :: os_list (:) !> Table containing OS tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ) :: profiles (:) !> Index in the list of profiles integer , intent ( inout ) :: profindex type ( toml_key ), allocatable :: key_list (:) character ( len = :), allocatable :: os_name , l_os_name type ( toml_table ), pointer :: os_node integer :: ios , stat , os_type logical :: is_valid , is_key_val if ( size ( os_list ) < 1 ) return do ios = 1 , size ( os_list ) os_name = os_list ( ios )% key call validate_os_name ( os_name , is_valid ) if ( is_valid ) then call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"os \" // os_name // \" has to be a table\" ) return end if call os_node % get_keys ( key_list ) call match_os_type ( os_name , os_type ) call get_flags ( profile_name , compiler_name , os_type , key_list , os_node , profiles , profindex , . true .) else ! Not lowercase OS name l_os_name = lower ( os_name ) call validate_os_name ( l_os_name , is_valid ) if ( is_valid ) then call fatal_error ( error , '*traverse_oss*:Error: Name of the operating system must be a lowercase string.' ) end if if ( allocated ( error )) return ! Missing OS name is_key_val = . false . os_name = os_list ( ios )% key call get_value ( table , os_name , os_node , stat = stat ) if ( stat /= toml_stat % success ) then is_key_val = . true . end if os_node => table os_type = OS_ALL call get_flags ( profile_name , compiler_name , os_type , os_list , os_node , profiles , profindex , . false .) end if end do end subroutine traverse_oss !> Traverse compiler tables subroutine traverse_compilers ( profile_name , comp_list , table , error , profiles_size , profiles , profindex ) !> Name of profile character ( len = :), allocatable , intent ( in ) :: profile_name !> List of OSs in table with profile name given type ( toml_key ), allocatable , intent ( in ) :: comp_list (:) !> Table containing compiler tables type ( toml_table ), pointer , intent ( in ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Number of profiles in list of profiles integer , intent ( inout ), optional :: profiles_size !> List of profiles type ( profile_config_t ), allocatable , intent ( inout ), optional :: profiles (:) !> Index in the list of profiles integer , intent ( inout ), optional :: profindex character ( len = :), allocatable :: compiler_name type ( toml_table ), pointer :: comp_node type ( toml_key ), allocatable :: os_list (:) integer :: icomp , stat logical :: is_valid if ( size ( comp_list ) < 1 ) return do icomp = 1 , size ( comp_list ) call validate_compiler_name ( comp_list ( icomp )% key , is_valid ) if ( is_valid ) then compiler_name = comp_list ( icomp )% key call get_value ( table , compiler_name , comp_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Compiler \" // comp_list ( icomp )% key // \" must be a table entry\" ) exit end if call comp_node % get_keys ( os_list ) if ( present ( profiles_size )) then call traverse_oss_for_size ( profile_name , compiler_name , os_list , comp_node , profiles_size , error ) if ( allocated ( error )) return else if (. not .( present ( profiles ). and . present ( profindex ))) then call fatal_error ( error , \"Both profiles and profindex have to be present\" ) return end if call traverse_oss ( profile_name , compiler_name , os_list , comp_node , & & profiles , profindex , error ) if ( allocated ( error )) return end if else call fatal_error ( error , '*traverse_compilers*:Error: Compiler name not specified or invalid.' ) end if end do end subroutine traverse_compilers !> Construct new profiles array from a TOML data structure subroutine new_profiles ( profiles , table , error ) !> Instance of the dependency configuration type ( profile_config_t ), allocatable , intent ( out ) :: profiles (:) !> Instance of the TOML data structure type ( toml_table ), target , intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: prof_node type ( toml_key ), allocatable :: prof_list (:) type ( toml_key ), allocatable :: comp_list (:) type ( toml_key ), allocatable :: os_list (:) character ( len = :), allocatable :: profile_name , compiler_name integer :: profiles_size , iprof , stat , profindex logical :: is_valid type ( profile_config_t ), allocatable :: default_profiles (:) path = '' default_profiles = get_default_profiles ( error ) if ( allocated ( error )) return call table % get_keys ( prof_list ) if ( size ( prof_list ) < 1 ) return profiles_size = 0 do iprof = 1 , size ( prof_list ) profile_name = prof_list ( iprof )% key call validate_compiler_name ( profile_name , is_valid ) if ( is_valid ) then profile_name = \"all\" comp_list = prof_list ( iprof : iprof ) prof_node => table call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles_size = profiles_size ) if ( allocated ( error )) return else call validate_os_name ( profile_name , is_valid ) if ( is_valid ) then os_list = prof_list ( iprof : iprof ) profile_name = 'all' compiler_name = DEFAULT_COMPILER call traverse_oss_for_size ( profile_name , compiler_name , os_list , table , profiles_size , error ) if ( allocated ( error )) return else call get_value ( table , profile_name , prof_node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Profile \" // prof_list ( iprof )% key // \" must be a table entry\" ) exit end if call prof_node % get_keys ( comp_list ) call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles_size = profiles_size ) if ( allocated ( error )) return end if end if end do profiles_size = profiles_size + size ( default_profiles ) allocate ( profiles ( profiles_size )) do profindex = 1 , size ( default_profiles ) profiles ( profindex ) = default_profiles ( profindex ) end do do iprof = 1 , size ( prof_list ) profile_name = prof_list ( iprof )% key call validate_compiler_name ( profile_name , is_valid ) if ( is_valid ) then profile_name = \"all\" comp_list = prof_list ( iprof : iprof ) prof_node => table call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles = profiles , profindex = profindex ) if ( allocated ( error )) return else call validate_os_name ( profile_name , is_valid ) if ( is_valid ) then os_list = prof_list ( iprof : iprof ) profile_name = 'all' compiler_name = DEFAULT_COMPILER prof_node => table call traverse_oss ( profile_name , compiler_name , os_list , prof_node , profiles , profindex , error ) if ( allocated ( error )) return else call get_value ( table , profile_name , prof_node , stat = stat ) call prof_node % get_keys ( comp_list ) call traverse_compilers ( profile_name , comp_list , prof_node , error , profiles = profiles , profindex = profindex ) if ( allocated ( error )) return end if end if end do ! Apply profiles with profile name 'all' to matching profiles do iprof = 1 , size ( profiles ) if ( profiles ( iprof )% profile_name . eq . 'all' ) then do profindex = 1 , size ( profiles ) if (. not .( profiles ( profindex )% profile_name . eq . 'all' ) & & . and .( profiles ( profindex )% compiler . eq . profiles ( iprof )% compiler ) & & . and .( profiles ( profindex )% os_type . eq . profiles ( iprof )% os_type )) then profiles ( profindex )% flags = profiles ( profindex )% flags // & & \" \" // profiles ( iprof )% flags profiles ( profindex )% c_flags = profiles ( profindex )% c_flags // & & \" \" // profiles ( iprof )% c_flags profiles ( profindex )% cxx_flags = profiles ( profindex )% cxx_flags // & & \" \" // profiles ( iprof )% cxx_flags profiles ( profindex )% link_time_flags = profiles ( profindex )% link_time_flags // & & \" \" // profiles ( iprof )% link_time_flags end if end do end if end do end subroutine new_profiles !> Construct an array of built-in profiles function get_default_profiles ( error ) result ( default_profiles ) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( profile_config_t ), allocatable :: default_profiles (:) default_profiles = [ & & new_profile ( 'release' , & & 'caf' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -funroll-loops' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'gfortran' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -funroll-loops -fcoarray=single' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'f95' , & & OS_ALL , & & flags = ' -O3 -Wimplicit-interface -fPIC -fmax-errors=1 -ffast-math -funroll-loops' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'nvfortran' , & & OS_ALL , & & flags = ' -Mbackslash' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifort' , & & OS_ALL , & & flags = ' -fp-model precise -pc64 -align all -error-limit 1 -reentrancy& & threaded -nogen-interfaces -assume byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifort' , & & OS_WINDOWS , & & flags = ' /fp:precise /align:all /error-limit:1 /reentrancy:threaded& & /nogen-interfaces /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifx' , & & OS_ALL , & & flags = ' -fp-model=precise -pc64 -align all -error-limit 1 -reentrancy& & threaded -nogen-interfaces -assume byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /fp:precise /align:all /error-limit:1 /reentrancy:threaded& & /nogen-interfaces /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'nagfor' , & & OS_ALL , & & flags = ' -O4 -coarray=single -PIC' , & & is_built_in = . true .), & & new_profile ( 'release' , & & 'lfortran' , & & OS_ALL , & & flags = ' flag_lfortran_opt' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'caf' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -fbacktrace' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'gfortran' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -fbacktrace -fcoarray=single' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'f95' , & & OS_ALL , & & flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g -fcheck=bounds& & -fcheck=array-temps -Wno-maybe-uninitialized -Wno-uninitialized -fbacktrace' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'nvfortran' , & & OS_ALL , & & flags = ' -Minform=inform -Mbackslash -g -Mbounds -Mchkptr -Mchkstk -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifort' , & & OS_ALL , & & flags = ' -warn all -check all -error-limit 1 -O0 -g -assume byterecl -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifort' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1& & /Od /Z7 /assume:byterecl /traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_ALL , & & flags = ' -warn all -check all -error-limit 1 -O0 -g -assume byterecl -traceback' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1 /Od /Z7 /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'ifx' , & & OS_WINDOWS , & & flags = ' /warn:all /check:all /error-limit:1 /Od /Z7 /assume:byterecl' , & & is_built_in = . true .), & & new_profile ( 'debug' , & & 'lfortran' , & & OS_ALL , & & flags = '' , & & is_built_in = . true .) & &] end function get_default_profiles !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the profile configuration class ( profile_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if write ( unit , fmt ) \"Profile\" if ( allocated ( self % profile_name )) then write ( unit , fmt ) \"- profile name\" , self % profile_name end if if ( allocated ( self % compiler )) then write ( unit , fmt ) \"- compiler\" , self % compiler end if write ( unit , fmt ) \"- os\" , os_type_name ( self % os_type ) if ( allocated ( self % flags )) then write ( unit , fmt ) \"- compiler flags\" , self % flags end if end subroutine info !> Print a representation of profile_config_t function info_profile ( profile ) result ( s ) !> Profile to be represented type ( profile_config_t ), intent ( in ) :: profile !> String representation of given profile character (:), allocatable :: s integer :: i s = \"profile_config_t(\" s = s // 'profile_name=\"' // profile % profile_name // '\"' s = s // ', compiler=\"' // profile % compiler // '\"' s = s // \", os_type=\" select case ( profile % os_type ) case ( OS_UNKNOWN ) s = s // \"OS_UNKNOWN\" case ( OS_LINUX ) s = s // \"OS_LINUX\" case ( OS_MACOS ) s = s // \"OS_MACOS\" case ( OS_WINDOWS ) s = s // \"OS_WINDOWS\" case ( OS_CYGWIN ) s = s // \"OS_CYGWIN\" case ( OS_SOLARIS ) s = s // \"OS_SOLARIS\" case ( OS_FREEBSD ) s = s // \"OS_FREEBSD\" case ( OS_OPENBSD ) s = s // \"OS_OPENBSD\" case ( OS_ALL ) s = s // \"OS_ALL\" case default s = s // \"INVALID\" end select if ( allocated ( profile % flags )) s = s // ', flags=\"' // profile % flags // '\"' if ( allocated ( profile % c_flags )) s = s // ', c_flags=\"' // profile % c_flags // '\"' if ( allocated ( profile % cxx_flags )) s = s // ', cxx_flags=\"' // profile % cxx_flags // '\"' if ( allocated ( profile % link_time_flags )) s = s // ', link_time_flags=\"' // profile % link_time_flags // '\"' if ( allocated ( profile % file_scope_flags )) then do i = 1 , size ( profile % file_scope_flags ) s = s // ', flags for ' // profile % file_scope_flags ( i )% file_name // & & ' =\"' // profile % file_scope_flags ( i )% flags // '\"' end do end if s = s // \")\" end function info_profile !> Look for profile with given configuration in array profiles subroutine find_profile ( profiles , profile_name , compiler , os_type , found_matching , chosen_profile ) !> Array of profiles type ( profile_config_t ), allocatable , intent ( in ) :: profiles (:) !> Name of profile character (:), allocatable , intent ( in ) :: profile_name !> Name of compiler character (:), allocatable , intent ( in ) :: compiler !> Type of operating system (enum) integer , intent ( in ) :: os_type !> Boolean value containing true if matching profile was found logical , intent ( out ) :: found_matching !> Last matching profile in the profiles array type ( profile_config_t ), intent ( out ) :: chosen_profile character (:), allocatable :: curr_profile_name character (:), allocatable :: curr_compiler integer :: curr_os integer :: i , priority , curr_priority found_matching = . false . if ( size ( profiles ) < 1 ) return ! Try to find profile with matching OS type do i = 1 , size ( profiles ) curr_profile_name = profiles ( i )% profile_name curr_compiler = profiles ( i )% compiler curr_os = profiles ( i )% os_type if ( curr_profile_name . eq . profile_name ) then if ( curr_compiler . eq . compiler ) then if ( curr_os . eq . os_type ) then chosen_profile = profiles ( i ) found_matching = . true . end if end if end if end do ! Try to find profile with OS type 'all' if (. not . found_matching ) then do i = 1 , size ( profiles ) curr_profile_name = profiles ( i )% profile_name curr_compiler = profiles ( i )% compiler curr_os = profiles ( i )% os_type if ( curr_profile_name . eq . profile_name ) then if ( curr_compiler . eq . compiler ) then if ( curr_os . eq . OS_ALL ) then chosen_profile = profiles ( i ) found_matching = . true . end if end if end if end do end if end subroutine find_profile logical function file_scope_same ( this , that ) class ( file_scope_flag ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that file_scope_same = . false . select type ( other => that ) type is ( file_scope_flag ) if ( allocated ( this % file_name ). neqv . allocated ( other % file_name )) return if ( allocated ( this % file_name )) then if (. not .( this % file_name == other % file_name )) return endif if ( allocated ( this % flags ). neqv . allocated ( other % flags )) return if ( allocated ( this % flags )) then if (. not .( this % flags == other % flags )) return endif class default ! Not the same type return end select !> All checks passed! file_scope_same = . true . end function file_scope_same !> Dump to toml table subroutine file_scope_dump ( self , table , error ) !> Instance of the serializable object class ( file_scope_flag ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_string ( table , \"file-name\" , self % file_name , error ) if ( allocated ( error )) return call set_string ( table , \"flags\" , self % flags , error ) if ( allocated ( error )) return end subroutine file_scope_dump !> Read from toml table (no checks made at this stage) subroutine file_scope_load ( self , table , error ) !> Instance of the serializable object class ( file_scope_flag ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"file-name\" , self % file_name ) call get_value ( table , \"flags\" , self % flags ) end subroutine file_scope_load logical function profile_same ( this , that ) class ( profile_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii profile_same = . false . select type ( other => that ) type is ( profile_config_t ) if ( allocated ( this % profile_name ). neqv . allocated ( other % profile_name )) return if ( allocated ( this % profile_name )) then if (. not .( this % profile_name == other % profile_name )) return endif if ( allocated ( this % compiler ). neqv . allocated ( other % compiler )) return if ( allocated ( this % compiler )) then if (. not .( this % compiler == other % compiler )) return endif if ( this % os_type /= other % os_type ) return if ( allocated ( this % flags ). neqv . allocated ( other % flags )) return if ( allocated ( this % flags )) then if (. not .( this % flags == other % flags )) return endif if ( allocated ( this % c_flags ). neqv . allocated ( other % c_flags )) return if ( allocated ( this % c_flags )) then if (. not .( this % c_flags == other % c_flags )) return endif if ( allocated ( this % cxx_flags ). neqv . allocated ( other % cxx_flags )) return if ( allocated ( this % cxx_flags )) then if (. not .( this % cxx_flags == other % cxx_flags )) return endif if ( allocated ( this % link_time_flags ). neqv . allocated ( other % link_time_flags )) return if ( allocated ( this % link_time_flags )) then if (. not .( this % link_time_flags == other % link_time_flags )) return endif if ( allocated ( this % file_scope_flags ). neqv . allocated ( other % file_scope_flags )) return if ( allocated ( this % file_scope_flags )) then if (. not . size ( this % file_scope_flags ) == size ( other % file_scope_flags )) return do ii = 1 , size ( this % file_scope_flags ) print * , 'check ii-th file scope: ' , ii if (. not . this % file_scope_flags ( ii ) == other % file_scope_flags ( ii )) return end do endif if ( this % is_built_in . neqv . other % is_built_in ) return class default ! Not the same type return end select !> All checks passed! profile_same = . true . end function profile_same !> Dump to toml table subroutine profile_dump ( self , table , error ) !> Instance of the serializable object class ( profile_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: ierr , ii type ( toml_table ), pointer :: ptr_deps , ptr character ( len = 30 ) :: unnamed call set_string ( table , \"profile-name\" , self % profile_name , error ) if ( allocated ( error )) return call set_string ( table , \"compiler\" , self % compiler , error ) if ( allocated ( error )) return call set_string ( table , \"os-type\" , os_type_name ( self % os_type ), error , 'profile_config_t' ) if ( allocated ( error )) return call set_string ( table , \"flags\" , self % flags , error ) if ( allocated ( error )) return call set_string ( table , \"c-flags\" , self % c_flags , error ) if ( allocated ( error )) return call set_string ( table , \"cxx-flags\" , self % cxx_flags , error ) if ( allocated ( error )) return call set_string ( table , \"link-time-flags\" , self % link_time_flags , error ) if ( allocated ( error )) return if ( allocated ( self % file_scope_flags )) then ! Create dependency table call add_table ( table , \"file-scope-flags\" , ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , \"profile_config_t cannot create file scope table \" ) return end if do ii = 1 , size ( self % file_scope_flags ) associate ( dep => self % file_scope_flags ( ii )) !> Because files need a name, fallback if this has no name if ( len_trim ( dep % file_name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_deps , trim ( unnamed ), ptr ) else call add_table ( ptr_deps , dep % file_name , ptr ) end if if (. not . associated ( ptr )) then call fatal_error ( error , \"profile_config_t cannot create entry for file \" // dep % file_name ) return end if call dep % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do endif call set_value ( table , \"is-built-in\" , self % is_built_in , error , 'profile_config_t' ) if ( allocated ( error )) return 1 format ( 'UNNAMED_FILE_' , i0 ) end subroutine profile_dump !> Read from toml table (no checks made at this stage) subroutine profile_load ( self , table , error ) !> Instance of the serializable object class ( profile_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: flag integer :: ii , jj type ( toml_table ), pointer :: ptr_dep , ptr type ( toml_key ), allocatable :: keys (:), dep_keys (:) call table % get_keys ( keys ) call get_value ( table , \"profile-name\" , self % profile_name ) call get_value ( table , \"compiler\" , self % compiler ) call get_value ( table , \"os-type\" , flag ) call match_os_type ( flag , self % os_type ) call get_value ( table , \"flags\" , self % flags ) call get_value ( table , \"c-flags\" , self % c_flags ) call get_value ( table , \"cxx-flags\" , self % cxx_flags ) call get_value ( table , \"link-time-flags\" , self % link_time_flags ) call get_value ( table , \"is-built-in\" , self % is_built_in , error , 'profile_config_t' ) if ( allocated ( error )) return if ( allocated ( self % file_scope_flags )) deallocate ( self % file_scope_flags ) sub_deps : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"file-scope-flags\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'profile_config_t: error retrieving file_scope_flags table' ) return end if !> Read all packages call ptr % get_keys ( dep_keys ) allocate ( self % file_scope_flags ( size ( dep_keys ))) do jj = 1 , size ( dep_keys ) call get_value ( ptr , dep_keys ( jj ), ptr_dep ) call self % file_scope_flags ( jj )% load_from_toml ( ptr_dep , error ) if ( allocated ( error )) return end do end select end do sub_deps end subroutine profile_load end module fpm_manifest_profile","tags":"","loc":"sourcefile/profiles.f90.html"},{"title":"fpm_backend_output.f90 – Fortran-lang/fpm","text":"Source Code !># Build Backend Progress Output !> This module provides a derived type `build_progress_t` for printing build status !> and progress messages to the console while the backend is building the package. !> !> The `build_progress_t` type supports two modes: `normal` and `plain` !> where the former does 'pretty' output and the latter does not. !> The `normal` mode is intended for typical interactive usage whereas !> 'plain' mode is used with the `--verbose` flag or when `stdout` is not attached !> to a terminal (e.g. when piping or redirecting `stdout`). In these cases, !> the pretty output must be suppressed to avoid control codes being output. module fpm_backend_output use iso_fortran_env , only : stdout => output_unit use fpm_filesystem , only : basename use fpm_targets , only : build_target_ptr use fpm_backend_console , only : console_t , LINE_RESET , COLOR_RED , COLOR_GREEN , COLOR_YELLOW , COLOR_RESET implicit none private public build_progress_t !> Build progress object type build_progress_t !> Console object for updating console lines type ( console_t ) :: console !> Number of completed targets integer :: n_complete !> Total number of targets scheduled integer :: n_target !> 'Plain' output (no colors or updating) logical :: plain_mode = . true . !> Store needed when updating previous console lines integer , allocatable :: output_lines (:) !> Queue of scheduled build targets type ( build_target_ptr ), pointer :: target_queue (:) contains !> Output 'compiling' status for build target procedure :: compiling_status => output_status_compiling !> Output 'complete' status for build target procedure :: completed_status => output_status_complete !> Output finished status for whole package procedure :: success => output_progress_success end type build_progress_t !> Constructor for build_progress_t interface build_progress_t procedure :: new_build_progress end interface build_progress_t contains !> Initialise a new build progress object function new_build_progress ( target_queue , plain_mode ) result ( progress ) !> The queue of scheduled targets type ( build_target_ptr ), intent ( in ), target :: target_queue (:) !> Enable 'plain' output for progress object logical , intent ( in ), optional :: plain_mode !> Progress object to initialise type ( build_progress_t ) :: progress progress % n_target = size ( target_queue , 1 ) progress % target_queue => target_queue progress % plain_mode = plain_mode progress % n_complete = 0 allocate ( progress % output_lines ( progress % n_target )) end function new_build_progress !> Output 'compiling' status for build target and overall percentage progress subroutine output_status_compiling ( progress , queue_index ) !> Progress object class ( build_progress_t ), intent ( inout ) :: progress !> Index of build target in the target queue integer , intent ( in ) :: queue_index character (:), allocatable :: target_name character ( 100 ) :: output_string character ( 7 ) :: overall_progress associate ( target => progress % target_queue ( queue_index )% ptr ) if ( allocated ( target % source )) then target_name = basename ( target % source % file_name ) else target_name = basename ( target % output_file ) end if write ( overall_progress , '(A,I3,A)' ) '[' , 100 * progress % n_complete / progress % n_target , '%] ' if ( progress % plain_mode ) then ! Plain output !$omp critical write ( * , '(A7,A30)' ) overall_progress , target_name !$omp end critical else ! Pretty output write ( output_string , '(A,T40,A,A)' ) target_name , COLOR_YELLOW // 'compiling...' // COLOR_RESET call progress % console % write_line ( trim ( output_string ), progress % output_lines ( queue_index )) call progress % console % write_line ( overall_progress // 'Compiling...' , advance = . false .) end if end associate end subroutine output_status_compiling !> Output 'complete' status for build target and update overall percentage progress subroutine output_status_complete ( progress , queue_index , build_stat ) !> Progress object class ( build_progress_t ), intent ( inout ) :: progress !> Index of build target in the target queue integer , intent ( in ) :: queue_index !> Build status flag integer , intent ( in ) :: build_stat character (:), allocatable :: target_name character ( 100 ) :: output_string character ( 7 ) :: overall_progress !$omp critical progress % n_complete = progress % n_complete + 1 !$omp end critical associate ( target => progress % target_queue ( queue_index )% ptr ) if ( allocated ( target % source )) then target_name = basename ( target % source % file_name ) else target_name = basename ( target % output_file ) end if if ( build_stat == 0 ) then write ( output_string , '(A,T40,A,A)' ) target_name , COLOR_GREEN // 'done.' // COLOR_RESET else write ( output_string , '(A,T40,A,A)' ) target_name , COLOR_RED // 'failed.' // COLOR_RESET end if write ( overall_progress , '(A,I3,A)' ) '[' , 100 * progress % n_complete / progress % n_target , '%] ' if ( progress % plain_mode ) then ! Plain output !$omp critical write ( * , '(A7,A30,A7)' ) overall_progress , target_name , 'done.' !$omp end critical else ! Pretty output call progress % console % update_line ( progress % output_lines ( queue_index ), trim ( output_string )) call progress % console % write_line ( overall_progress // 'Compiling...' , advance = . false .) end if end associate end subroutine output_status_complete !> Output finished status for whole package subroutine output_progress_success ( progress ) class ( build_progress_t ), intent ( inout ) :: progress if ( progress % plain_mode ) then ! Plain output write ( * , '(A)' ) '[100%] Project compiled successfully.' else ! Pretty output write ( * , '(A)' ) LINE_RESET // COLOR_GREEN // '[100%] Project compiled successfully.' // COLOR_RESET end if end subroutine output_progress_success end module fpm_backend_output","tags":"","loc":"sourcefile/fpm_backend_output.f90.html"},{"title":"fpm_targets.f90 – Fortran-lang/fpm","text":"Source Code !># Build target handling !> !> This module handles the construction of the build target list !> from the sources list (`[[targets_from_sources]]`), the !> resolution of module-dependencies between build targets !> (`[[resolve_module_dependencies]]`), and the enumeration of !> objects required for link targets (`[[resolve_target_linking]]`). !> !> A build target (`[[build_target_t]]`) is a file to be generated !> by the backend (compilation and linking). !> !> @note The current implementation is ignorant to the existence of !> module files (`.mod`,`.smod`). Dependencies arising from modules !> are based on the corresponding object files (`.o`) only. !> !> For more information, please read the documentation for the procedures: !> !> - `[[build_target_list]]` !> - `[[resolve_module_dependencies]]` !> !>### Enumerations !> !> __Target type:__ `FPM_TARGET_*` !> Describes the type of build target — determines backend build rules !> module fpm_targets use iso_fortran_env , only : int64 use fpm_error , only : error_t , fatal_error , fpm_stop use fpm_model use fpm_compiler , only : compiler_t use fpm_environment , only : get_os_type , OS_WINDOWS , OS_MACOS use fpm_filesystem , only : dirname , join_path , canon_path use fpm_strings , only : string_t , operator (. in .), string_cat , fnv_1a , resize , lower , str_ends_with use fpm_compiler , only : get_macros use fpm_sources , only : get_exe_name_with_suffix use fpm_manifest_preprocess , only : preprocess_config_t implicit none private public FPM_TARGET_UNKNOWN , FPM_TARGET_EXECUTABLE , & FPM_TARGET_ARCHIVE , FPM_TARGET_OBJECT , & FPM_TARGET_C_OBJECT , FPM_TARGET_CPP_OBJECT , & FPM_TARGET_NAME public build_target_t , build_target_ptr public targets_from_sources , resolve_module_dependencies public add_target , add_dependency public filter_library_targets , filter_executable_targets , filter_modules !> Target type is unknown (ignored) integer , parameter :: FPM_TARGET_UNKNOWN = - 1 !> Target type is executable integer , parameter :: FPM_TARGET_EXECUTABLE = 1 !> Target type is library archive integer , parameter :: FPM_TARGET_ARCHIVE = 2 !> Target type is compiled object integer , parameter :: FPM_TARGET_OBJECT = 3 !> Target type is c compiled object integer , parameter :: FPM_TARGET_C_OBJECT = 4 !> Target type is cpp compiled object integer , parameter :: FPM_TARGET_CPP_OBJECT = 5 !> Wrapper type for constructing arrays of `[[build_target_t]]` pointers type build_target_ptr type ( build_target_t ), pointer :: ptr => null () end type build_target_ptr !> Type describing a generated build target type build_target_t !> File path of build target object relative to cwd character (:), allocatable :: output_file !> File path of build target object relative to output_dir character (:), allocatable :: output_name !> File path of output directory character (:), allocatable :: output_dir !> File path of build log file relative to cwd character (:), allocatable :: output_log_file !> Name of parent package character (:), allocatable :: package_name !> Primary source for this build target type ( srcfile_t ), allocatable :: source !> Resolved build dependencies type ( build_target_ptr ), allocatable :: dependencies (:) !> Target type integer :: target_type = FPM_TARGET_UNKNOWN !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> Objects needed to link this target type ( string_t ), allocatable :: link_objects (:) !> Link flags for this build target character (:), allocatable :: link_flags !> Compile flags for this build target character (:), allocatable :: compile_flags !> Flag set when first visited to check for circular dependencies logical :: touched = . false . !> Flag set if build target is sorted for building logical :: sorted = . false . !> Flag set if build target will be skipped (not built) logical :: skip = . false . !> Language features type ( fortran_features_t ) :: features !> Targets in the same schedule group are guaranteed to be independent integer :: schedule = - 1 !> Previous source file hash integer ( int64 ), allocatable :: digest_cached !> List of macros type ( string_t ), allocatable :: macros (:) !> Version number character (:), allocatable :: version contains procedure :: is_executable_target end type build_target_t contains !> Target type name pure function FPM_TARGET_NAME ( type ) result ( msg ) integer , intent ( in ) :: type character (:), allocatable :: msg select case ( type ) case ( FPM_TARGET_ARCHIVE ); msg = 'Archive' case ( FPM_TARGET_CPP_OBJECT ); msg = 'C++ object' case ( FPM_TARGET_C_OBJECT ); msg = 'C Object' case ( FPM_TARGET_EXECUTABLE ); msg = 'Executable' case ( FPM_TARGET_OBJECT ); msg = 'Object' case default ; msg = 'Unknown' end select end function FPM_TARGET_NAME !> High-level wrapper to generate build target information subroutine targets_from_sources ( targets , model , prune , error ) !> The generated list of build targets type ( build_target_ptr ), intent ( out ), allocatable :: targets (:) !> The package model from which to construct the target list type ( fpm_model_t ), intent ( inout ), target :: model !> Enable tree-shaking/pruning of module dependencies logical , intent ( in ) :: prune !> Error structure type ( error_t ), intent ( out ), allocatable :: error call build_target_list ( targets , model ) call collect_exe_link_dependencies ( targets ) call resolve_module_dependencies ( targets , model % external_modules , error ) if ( allocated ( error )) return if ( prune ) then call prune_build_targets ( targets , root_package = model % package_name ) end if call resolve_target_linking ( targets , model ) end subroutine targets_from_sources !> Constructs a list of build targets from a list of source files !> !>### Source-target mapping !> !> One compiled object target (`FPM_TARGET_OBJECT`) is generated for each !> non-executable source file (`FPM_UNIT_MODULE`,`FPM_UNIT_SUBMODULE`, !> `FPM_UNIT_SUBPROGRAM`,`FPM_UNIT_CSOURCE`). !> !> If any source file has scope `FPM_SCOPE_LIB` (*i.e.* there are library sources) !> then the first target in the target list will be a library archive target !> (`FPM_TARGET_ARCHIVE`). The archive target will have a dependency on every !> compiled object target corresponding to a library source file. !> !> One compiled object target (`FPM_TARGET_OBJECT`) and one executable target (`FPM_TARGET_EXECUTABLE`) is !> generated for each exectuable source file (`FPM_UNIT_PROGRAM`). The exectuble target !> always has a dependency on the corresponding compiled object target. If there !> is a library, then the executable target has an additional dependency on the library !> archive target. !> subroutine build_target_list ( targets , model ) !> The generated list of build targets type ( build_target_ptr ), intent ( out ), allocatable :: targets (:) !> The package model from which to construct the target list type ( fpm_model_t ), intent ( inout ), target :: model integer :: i , j , n_source , exe_type character (:), allocatable :: exe_dir , compile_flags logical :: with_lib ! Initialize targets allocate ( targets ( 0 )) ! Check for empty build (e.g. header-only lib) n_source = sum ([( size ( model % packages ( j )% sources ), & j = 1 , size ( model % packages ))]) if ( n_source < 1 ) return with_lib = any ([(( model % packages ( j )% sources ( i )% unit_scope == FPM_SCOPE_LIB , & i = 1 , size ( model % packages ( j )% sources )), & j = 1 , size ( model % packages ))]) if ( with_lib ) call add_target ( targets , package = model % package_name , type = FPM_TARGET_ARCHIVE ,& output_name = join_path (& model % package_name , 'lib' // model % package_name // '.a' )) do j = 1 , size ( model % packages ) associate ( sources => model % packages ( j )% sources ) do i = 1 , size ( sources ) if (. not . model % include_tests ) then if ( sources ( i )% unit_scope == FPM_SCOPE_TEST ) cycle end if select case ( sources ( i )% unit_type ) case ( FPM_UNIT_MODULE , FPM_UNIT_SUBMODULE , FPM_UNIT_SUBPROGRAM , FPM_UNIT_CSOURCE ) call add_target ( targets , package = model % packages ( j )% name , source = sources ( i ), & type = merge ( FPM_TARGET_C_OBJECT , FPM_TARGET_OBJECT ,& sources ( i )% unit_type == FPM_UNIT_CSOURCE ), & output_name = get_object_name ( sources ( i )), & features = model % packages ( j )% features , & preprocess = model % packages ( j )% preprocess , & version = model % packages ( j )% version ) if ( with_lib . and . sources ( i )% unit_scope == FPM_SCOPE_LIB ) then ! Archive depends on object call add_dependency ( targets ( 1 )% ptr , targets ( size ( targets ))% ptr ) end if case ( FPM_UNIT_CPPSOURCE ) call add_target ( targets , package = model % packages ( j )% name , source = sources ( i ), & type = FPM_TARGET_CPP_OBJECT , & output_name = get_object_name ( sources ( i )), & preprocess = model % packages ( j )% preprocess , & version = model % packages ( j )% version ) if ( with_lib . and . sources ( i )% unit_scope == FPM_SCOPE_LIB ) then ! Archive depends on object call add_dependency ( targets ( 1 )% ptr , targets ( size ( targets ))% ptr ) end if !> Add stdc++ as a linker flag. If not already there. if (. not . ( \"stdc++\" . in . model % link_libraries )) then if ( get_os_type () == OS_MACOS ) then model % link_libraries = [ model % link_libraries , string_t ( \"c++\" )] else model % link_libraries = [ model % link_libraries , string_t ( \"stdc++\" )] end if end if case ( FPM_UNIT_PROGRAM ) if ( str_ends_with ( lower ( sources ( i )% file_name ), [ \".c\" ])) then exe_type = FPM_TARGET_C_OBJECT else if ( str_ends_with ( lower ( sources ( i )% file_name ), [ \".cpp\" , \".cc \" ])) then exe_type = FPM_TARGET_CPP_OBJECT else ! Default to a Fortran object exe_type = FPM_TARGET_OBJECT end if call add_target ( targets , package = model % packages ( j )% name , type = exe_type ,& output_name = get_object_name ( sources ( i )), & source = sources ( i ), & features = model % packages ( j )% features , & preprocess = model % packages ( j )% preprocess & ) if ( sources ( i )% unit_scope == FPM_SCOPE_APP ) then exe_dir = 'app' else if ( sources ( i )% unit_scope == FPM_SCOPE_EXAMPLE ) then exe_dir = 'example' else exe_dir = 'test' end if call add_target ( targets , package = model % packages ( j )% name , type = FPM_TARGET_EXECUTABLE ,& link_libraries = sources ( i )% link_libraries , & output_name = join_path ( exe_dir , get_exe_name_with_suffix ( sources ( i )))) associate ( target => targets ( size ( targets ))% ptr ) ! Linker-only flags are necessary on some compilers for codes with non-Fortran main select case ( exe_type ) case ( FPM_TARGET_C_OBJECT ) call model % compiler % get_main_flags ( \"c\" , compile_flags ) case ( FPM_TARGET_CPP_OBJECT ) call model % compiler % get_main_flags ( \"c++\" , compile_flags ) case default compile_flags = \"\" end select target % compile_flags = target % compile_flags // ' ' // compile_flags ! Executable depends on object call add_dependency ( target , targets ( size ( targets ) - 1 )% ptr ) if ( with_lib ) then ! Executable depends on library call add_dependency ( target , targets ( 1 )% ptr ) end if endassociate end select end do end associate end do contains function get_object_name ( source ) result ( object_file ) ! Generate object target path from source name and model params ! ! type ( srcfile_t ), intent ( in ) :: source character (:), allocatable :: object_file integer :: i character ( 1 ), parameter :: filesep = '/' object_file = canon_path ( source % file_name ) ! Convert any remaining directory separators to underscores i = index ( object_file , filesep ) do while ( i > 0 ) object_file ( i : i ) = '_' i = index ( object_file , filesep ) end do object_file = join_path ( model % package_name , object_file ) // '.o' end function get_object_name end subroutine build_target_list !> Add non-library non-module dependencies for executable targets !> !> Executable targets will link to any non-program non-module source files that !> are in the same directory or in a subdirectory. !> !> (Note: Fortran module dependencies are handled separately in !> `resolve_module_dependencies` and `resolve_target_linking`.) !> subroutine collect_exe_link_dependencies ( targets ) type ( build_target_ptr ), intent ( inout ) :: targets (:) integer :: i , j character (:), allocatable :: exe_source_dir ! Add non-module dependencies for executables do j = 1 , size ( targets ) if ( targets ( j )% ptr % target_type == FPM_TARGET_EXECUTABLE ) then do i = 1 , size ( targets ) if ( i == j ) cycle associate ( exe => targets ( j )% ptr , dep => targets ( i )% ptr ) exe_source_dir = dirname ( exe % dependencies ( 1 )% ptr % source % file_name ) if ( allocated ( dep % source )) then if ( dep % source % unit_scope /= FPM_SCOPE_LIB . and . & dep % source % unit_type /= FPM_UNIT_PROGRAM . and . & dep % source % unit_type /= FPM_UNIT_MODULE . and . & index ( dirname ( dep % source % file_name ), exe_source_dir ) == 1 ) then call add_dependency ( exe , dep ) end if end if end associate end do end if end do end subroutine collect_exe_link_dependencies !> Allocate a new target and append to target list subroutine add_target ( targets , package , type , output_name , source , link_libraries , & & features , preprocess , version ) type ( build_target_ptr ), allocatable , intent ( inout ) :: targets (:) character ( * ), intent ( in ) :: package integer , intent ( in ) :: type character ( * ), intent ( in ) :: output_name type ( srcfile_t ), intent ( in ), optional :: source type ( string_t ), intent ( in ), optional :: link_libraries (:) type ( fortran_features_t ), intent ( in ), optional :: features type ( preprocess_config_t ), intent ( in ), optional :: preprocess character ( * ), intent ( in ), optional :: version integer :: i type ( build_target_t ), pointer :: new_target if (. not . allocated ( targets )) allocate ( targets ( 0 )) ! Check for duplicate outputs do i = 1 , size ( targets ) if ( targets ( i )% ptr % output_name == output_name ) then write ( * , * ) 'Error while building target list: duplicate output object \"' ,& output_name , '\"' if ( present ( source )) write ( * , * ) ' Source file: \"' , source % file_name , '\"' call fpm_stop ( 1 , ' ' ) end if end do allocate ( new_target ) new_target % target_type = type new_target % output_name = output_name new_target % package_name = package if ( present ( source )) new_target % source = source if ( present ( link_libraries )) new_target % link_libraries = link_libraries if ( present ( features )) new_target % features = features if ( present ( preprocess )) then if ( allocated ( preprocess % macros )) new_target % macros = preprocess % macros endif if ( present ( version )) new_target % version = version allocate ( new_target % dependencies ( 0 )) targets = [ targets , build_target_ptr ( new_target )] end subroutine add_target !> Add pointer to dependeny in target%dependencies subroutine add_dependency ( target , dependency ) type ( build_target_t ), intent ( inout ) :: target type ( build_target_t ) , intent ( in ), target :: dependency target % dependencies = [ target % dependencies , build_target_ptr ( dependency )] end subroutine add_dependency !> Add dependencies to source-based targets (`FPM_TARGET_OBJECT`) !> based on any modules used by the corresponding source file. !> !>### Source file scoping !> !> Source files are assigned a scope of either `FPM_SCOPE_LIB`, !> `FPM_SCOPE_APP` or `FPM_SCOPE_TEST`. The scope controls which !> modules may be used by the source file: !> !> - Library sources (`FPM_SCOPE_LIB`) may only use modules !> also with library scope. This includes library modules !> from dependencies. !> !> - Executable sources (`FPM_SCOPE_APP`,`FPM_SCOPE_TEST`) may use !> library modules (including dependencies) as well as any modules !> corresponding to source files in the same directory or a !> subdirectory of the executable source file. !> !> @warning If a module used by a source file cannot be resolved to !> a source file in the package of the correct scope, then a __fatal error__ !> is returned by the procedure and model construction fails. !> subroutine resolve_module_dependencies ( targets , external_modules , error ) type ( build_target_ptr ), intent ( inout ), target :: targets (:) type ( string_t ), intent ( in ) :: external_modules (:) type ( error_t ), allocatable , intent ( out ) :: error type ( build_target_ptr ) :: dep integer :: i , j do i = 1 , size ( targets ) if (. not . allocated ( targets ( i )% ptr % source )) cycle do j = 1 , size ( targets ( i )% ptr % source % modules_used ) if ( targets ( i )% ptr % source % modules_used ( j )% s . in . targets ( i )% ptr % source % modules_provided ) then ! Dependency satisfied in same file, skip cycle end if if ( targets ( i )% ptr % source % modules_used ( j )% s . in . external_modules ) then ! Dependency satisfied in system-installed module cycle end if if ( any ( targets ( i )% ptr % source % unit_scope == & [ FPM_SCOPE_APP , FPM_SCOPE_EXAMPLE , FPM_SCOPE_TEST ])) then dep % ptr => & find_module_dependency ( targets , targets ( i )% ptr % source % modules_used ( j )% s , & include_dir = dirname ( targets ( i )% ptr % source % file_name )) else dep % ptr => & find_module_dependency ( targets , targets ( i )% ptr % source % modules_used ( j )% s ) end if if (. not . associated ( dep % ptr )) then call fatal_error ( error , & 'Unable to find source for module dependency: \"' // & targets ( i )% ptr % source % modules_used ( j )% s // & '\" used by \"' // targets ( i )% ptr % source % file_name // '\"' ) return end if call add_dependency ( targets ( i )% ptr , dep % ptr ) end do end do end subroutine resolve_module_dependencies function find_module_dependency ( targets , module_name , include_dir ) result ( target_ptr ) ! Find a module dependency in the library or a dependency library ! ! 'include_dir' specifies an allowable non-library search directory ! (Used for executable dependencies) ! type ( build_target_ptr ), intent ( in ), target :: targets (:) character ( * ), intent ( in ) :: module_name character ( * ), intent ( in ), optional :: include_dir type ( build_target_t ), pointer :: target_ptr integer :: k , l target_ptr => NULL () do k = 1 , size ( targets ) if (. not . allocated ( targets ( k )% ptr % source )) cycle do l = 1 , size ( targets ( k )% ptr % source % modules_provided ) if ( module_name == targets ( k )% ptr % source % modules_provided ( l )% s ) then select case ( targets ( k )% ptr % source % unit_scope ) case ( FPM_SCOPE_LIB , FPM_SCOPE_DEP ) target_ptr => targets ( k )% ptr exit case default if ( present ( include_dir )) then if ( index ( dirname ( targets ( k )% ptr % source % file_name ), include_dir ) == 1 ) then ! source file is within the include_dir or a subdirectory target_ptr => targets ( k )% ptr exit end if end if end select end if end do end do end function find_module_dependency !> Perform tree-shaking to remove unused module targets subroutine prune_build_targets ( targets , root_package ) !> Build target list to prune type ( build_target_ptr ), intent ( inout ), allocatable :: targets (:) !> Name of root package character ( * ), intent ( in ) :: root_package integer :: i , j , nexec type ( string_t ), allocatable :: modules_used (:) logical :: exclude_target ( size ( targets )) logical , allocatable :: exclude_from_archive (:) if ( size ( targets ) < 1 ) then return end if nexec = 0 allocate ( modules_used ( 0 )) ! Enumerate modules used by executables, non-module subprograms and their dependencies do i = 1 , size ( targets ) if ( targets ( i )% ptr % target_type == FPM_TARGET_EXECUTABLE ) then nexec = nexec + 1 call collect_used_modules ( targets ( i )% ptr ) elseif ( allocated ( targets ( i )% ptr % source )) then if ( targets ( i )% ptr % source % unit_type == FPM_UNIT_SUBPROGRAM ) then call collect_used_modules ( targets ( i )% ptr ) end if end if end do ! If there aren't any executables, then prune ! based on modules used in root package if ( nexec < 1 ) then do i = 1 , size ( targets ) if ( targets ( i )% ptr % package_name == root_package . and . & targets ( i )% ptr % target_type /= FPM_TARGET_ARCHIVE ) then call collect_used_modules ( targets ( i )% ptr ) end if end do end if call reset_target_flags ( targets ) exclude_target (:) = . false . ! Exclude purely module targets if they are not used anywhere do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( allocated ( target % source )) then if ( target % source % unit_type == FPM_UNIT_MODULE ) then exclude_target ( i ) = . true . target % skip = . true . do j = 1 , size ( target % source % modules_provided ) if ( target % source % modules_provided ( j )% s . in . modules_used ) then exclude_target ( i ) = . false . target % skip = . false . end if end do elseif ( target % source % unit_type == FPM_UNIT_SUBMODULE ) then ! Remove submodules if their parents are not used exclude_target ( i ) = . true . target % skip = . true . do j = 1 , size ( target % source % parent_modules ) if ( target % source % parent_modules ( j )% s . in . modules_used ) then exclude_target ( i ) = . false . target % skip = . false . end if end do end if end if ! (If there aren't any executables then we only prune modules from dependencies) if ( nexec < 1 . and . target % package_name == root_package ) then exclude_target ( i ) = . false . target % skip = . false . end if end associate end do targets = pack ( targets ,. not . exclude_target ) ! Remove unused targets from archive dependency list if ( targets ( 1 )% ptr % target_type == FPM_TARGET_ARCHIVE ) then associate ( archive => targets ( 1 )% ptr ) allocate ( exclude_from_archive ( size ( archive % dependencies ))) exclude_from_archive (:) = . false . do i = 1 , size ( archive % dependencies ) if ( archive % dependencies ( i )% ptr % skip ) then exclude_from_archive ( i ) = . true . end if end do archive % dependencies = pack ( archive % dependencies ,. not . exclude_from_archive ) end associate end if contains !> Recursively collect which modules are actually used recursive subroutine collect_used_modules ( target ) type ( build_target_t ), intent ( inout ) :: target integer :: j , k if ( target % touched ) then return else target % touched = . true . end if if ( allocated ( target % source )) then ! Add modules from this target and from any of it's children submodules do j = 1 , size ( target % source % modules_provided ) if (. not .( target % source % modules_provided ( j )% s . in . modules_used )) then modules_used = [ modules_used , target % source % modules_provided ( j )] end if ! Recurse into child submodules do k = 1 , size ( targets ) if ( allocated ( targets ( k )% ptr % source )) then if ( targets ( k )% ptr % source % unit_type == FPM_UNIT_SUBMODULE ) then if ( target % source % modules_provided ( j )% s . in . targets ( k )% ptr % source % parent_modules ) then call collect_used_modules ( targets ( k )% ptr ) end if end if end if end do end do end if ! Recurse into dependencies do j = 1 , size ( target % dependencies ) if ( target % dependencies ( j )% ptr % target_type /= FPM_TARGET_ARCHIVE ) then call collect_used_modules ( target % dependencies ( j )% ptr ) end if end do end subroutine collect_used_modules !> Reset target flags after recursive search subroutine reset_target_flags ( targets ) type ( build_target_ptr ), intent ( inout ) :: targets (:) integer :: i do i = 1 , size ( targets ) targets ( i )% ptr % touched = . false . end do end subroutine reset_target_flags end subroutine prune_build_targets !> Construct the linker flags string for each target !> `target%link_flags` includes non-library objects and library flags !> subroutine resolve_target_linking ( targets , model ) type ( build_target_ptr ), intent ( inout ), target :: targets (:) type ( fpm_model_t ), intent ( in ) :: model integer :: i character (:), allocatable :: global_link_flags , local_link_flags character (:), allocatable :: global_include_flags if ( size ( targets ) == 0 ) return global_link_flags = \"\" if ( allocated ( model % link_libraries )) then if ( size ( model % link_libraries ) > 0 ) then global_link_flags = model % compiler % enumerate_libraries ( global_link_flags , model % link_libraries ) end if end if allocate ( character ( 0 ) :: global_include_flags ) if ( allocated ( model % include_dirs )) then if ( size ( model % include_dirs ) > 0 ) then global_include_flags = global_include_flags // & & \" -I\" // string_cat ( model % include_dirs , \" -I\" ) end if end if do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) ! If the main program is a C/C++ one, some compilers require additional linking flags, see ! https://stackoverflow.com/questions/36221612/p3dfft-compilation-ifort-compiler-error-multiple-definiton-of-main ! In this case, compile_flags were already allocated if (. not . allocated ( target % compile_flags )) allocate ( character ( len = 0 ) :: target % compile_flags ) target % compile_flags = target % compile_flags // ' ' select case ( target % target_type ) case ( FPM_TARGET_C_OBJECT ) target % compile_flags = target % compile_flags // model % c_compile_flags case ( FPM_TARGET_CPP_OBJECT ) target % compile_flags = target % compile_flags // model % cxx_compile_flags case default target % compile_flags = target % compile_flags // model % fortran_compile_flags & & // get_feature_flags ( model % compiler , target % features ) end select !> Get macros as flags. target % compile_flags = target % compile_flags // get_macros ( model % compiler % id , & target % macros , & target % version ) if ( len ( global_include_flags ) > 0 ) then target % compile_flags = target % compile_flags // global_include_flags end if target % output_dir = get_output_dir ( model % build_prefix , target % compile_flags ) target % output_file = join_path ( target % output_dir , target % output_name ) target % output_log_file = join_path ( target % output_dir , target % output_name ) // '.log' end associate end do call add_include_build_dirs ( model , targets ) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) allocate ( target % link_objects ( 0 )) if ( target % target_type == FPM_TARGET_ARCHIVE ) then global_link_flags = target % output_file // global_link_flags call get_link_objects ( target % link_objects , target , is_exe = . false .) allocate ( character ( 0 ) :: target % link_flags ) else if ( target % target_type == FPM_TARGET_EXECUTABLE ) then call get_link_objects ( target % link_objects , target , is_exe = . true .) local_link_flags = \"\" if ( allocated ( model % link_flags )) local_link_flags = model % link_flags target % link_flags = model % link_flags // \" \" // string_cat ( target % link_objects , \" \" ) if ( allocated ( target % link_libraries )) then if ( size ( target % link_libraries ) > 0 ) then target % link_flags = model % compiler % enumerate_libraries ( target % link_flags , target % link_libraries ) local_link_flags = model % compiler % enumerate_libraries ( local_link_flags , target % link_libraries ) end if end if target % link_flags = target % link_flags // \" \" // global_link_flags target % output_dir = get_output_dir ( model % build_prefix , & & target % compile_flags // local_link_flags ) target % output_file = join_path ( target % output_dir , target % output_name ) target % output_log_file = join_path ( target % output_dir , target % output_name ) // '.log' end if end associate end do contains !> Wrapper to build link object list !> !> For libraries: just list dependency objects of lib target !> !> For executables: need to recursively discover non-library !> dependency objects. (i.e. modules in same dir as program) !> recursive subroutine get_link_objects ( link_objects , target , is_exe ) type ( string_t ), intent ( inout ), allocatable :: link_objects (:) type ( build_target_t ), intent ( in ) :: target logical , intent ( in ) :: is_exe integer :: i type ( string_t ) :: temp_str if (. not . allocated ( target % dependencies )) return do i = 1 , size ( target % dependencies ) associate ( dep => target % dependencies ( i )% ptr ) if (. not . allocated ( dep % source )) cycle ! Skip library dependencies for executable targets ! since the library archive will always be linked if ( is_exe . and .( dep % source % unit_scope == FPM_SCOPE_LIB )) cycle ! Skip if dependency object already listed if ( dep % output_file . in . link_objects ) cycle ! Add dependency object file to link object list temp_str % s = dep % output_file link_objects = [ link_objects , temp_str ] ! For executable objects, also need to include non-library ! dependencies from dependencies (recurse) if ( is_exe ) call get_link_objects ( link_objects , dep , is_exe = . true .) end associate end do end subroutine get_link_objects end subroutine resolve_target_linking subroutine add_include_build_dirs ( model , targets ) type ( fpm_model_t ), intent ( in ) :: model type ( build_target_ptr ), intent ( inout ), target :: targets (:) integer :: i type ( string_t ), allocatable :: build_dirs (:) type ( string_t ) :: temp allocate ( build_dirs ( 0 )) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( target % target_type /= FPM_TARGET_OBJECT ) cycle if ( target % output_dir . in . build_dirs ) cycle temp % s = target % output_dir build_dirs = [ build_dirs , temp ] end associate end do do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( target % target_type /= FPM_TARGET_OBJECT ) cycle target % compile_flags = target % compile_flags // & \" \" // model % compiler % get_module_flag ( target % output_dir ) // & \" -I\" // string_cat ( build_dirs , \" -I\" ) end associate end do end subroutine add_include_build_dirs function get_output_dir ( build_prefix , args ) result ( path ) character ( len =* ), intent ( in ) :: build_prefix character ( len =* ), intent ( in ) :: args character ( len = :), allocatable :: path character ( len = 16 ) :: build_hash write ( build_hash , '(z16.16)' ) fnv_1a ( args ) path = build_prefix // \"_\" // build_hash end function get_output_dir subroutine filter_library_targets ( targets , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , n n = 0 call resize ( list ) do i = 1 , size ( targets ) if ( targets ( i )% ptr % target_type == FPM_TARGET_ARCHIVE ) then if ( n >= size ( list )) call resize ( list ) n = n + 1 list ( n )% s = targets ( i )% ptr % output_file end if end do call resize ( list , n ) end subroutine filter_library_targets subroutine filter_executable_targets ( targets , scope , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) integer , intent ( in ) :: scope type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , n n = 0 call resize ( list ) do i = 1 , size ( targets ) if ( is_executable_target ( targets ( i )% ptr , scope )) then if ( n >= size ( list )) call resize ( list ) n = n + 1 list ( n )% s = targets ( i )% ptr % output_file end if end do call resize ( list , n ) end subroutine filter_executable_targets elemental function is_executable_target ( target_ptr , scope ) result ( is_exe ) class ( build_target_t ), intent ( in ) :: target_ptr integer , intent ( in ) :: scope logical :: is_exe is_exe = target_ptr % target_type == FPM_TARGET_EXECUTABLE . and . & allocated ( target_ptr % dependencies ) if ( is_exe ) then is_exe = target_ptr % dependencies ( 1 )% ptr % source % unit_scope == scope end if end function is_executable_target subroutine filter_modules ( targets , list ) type ( build_target_ptr ), intent ( in ) :: targets (:) type ( string_t ), allocatable , intent ( out ) :: list (:) integer :: i , j , n n = 0 call resize ( list ) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if (. not . allocated ( target % source )) cycle if ( target % source % unit_type == FPM_UNIT_SUBMODULE ) cycle if ( n + size ( target % source % modules_provided ) >= size ( list )) call resize ( list ) do j = 1 , size ( target % source % modules_provided ) n = n + 1 list ( n )% s = join_path ( target % output_dir , & target % source % modules_provided ( j )% s ) end do end associate end do call resize ( list , n ) end subroutine filter_modules function get_feature_flags ( compiler , features ) result ( flags ) type ( compiler_t ), intent ( in ) :: compiler type ( fortran_features_t ), intent ( in ) :: features character (:), allocatable :: flags flags = \"\" if ( features % implicit_typing ) then flags = flags // compiler % get_feature_flag ( \"implicit-typing\" ) else flags = flags // compiler % get_feature_flag ( \"no-implicit-typing\" ) end if if ( features % implicit_external ) then flags = flags // compiler % get_feature_flag ( \"implicit-external\" ) else flags = flags // compiler % get_feature_flag ( \"no-implicit-external\" ) end if if ( allocated ( features % source_form )) then flags = flags // compiler % get_feature_flag ( features % source_form // \"-form\" ) end if end function get_feature_flags end module fpm_targets","tags":"","loc":"sourcefile/fpm_targets.f90.html"},{"title":"fpm_sources.f90 – Fortran-lang/fpm","text":"Source Code !># Discovery of sources !> !> This module implements subroutines for building a list of !> `[[srcfile_t]]` objects by looking for source files in the filesystem. !> module fpm_sources use fpm_error , only : error_t use fpm_model , only : srcfile_t , FPM_UNIT_PROGRAM use fpm_filesystem , only : basename , canon_path , dirname , join_path , list_files , is_hidden_file use fpm_environment , only : get_os_type , OS_WINDOWS use fpm_strings , only : lower , str_ends_with , string_t , operator (. in .) use fpm_source_parsing , only : parse_f_source , parse_c_source use fpm_manifest_executable , only : executable_config_t implicit none private public :: add_sources_from_dir , add_executable_sources public :: get_exe_name_with_suffix character ( 4 ), parameter :: fortran_suffixes ( 2 ) = [ \".f90\" , & \".f \" ] character ( 4 ), parameter :: c_suffixes ( 4 ) = [ \".c \" , \".h \" , \".cpp\" , \".hpp\" ] contains !> Wrapper to source parsing routines. !> Selects parsing routine based on source file name extension function parse_source ( source_file_path , custom_f_ext , error ) result ( source ) character ( * ), intent ( in ) :: source_file_path type ( string_t ), optional , intent ( in ) :: custom_f_ext (:) type ( error_t ), allocatable , intent ( out ) :: error type ( srcfile_t ) :: source type ( string_t ), allocatable :: f_ext (:) call list_fortran_suffixes ( f_ext , custom_f_ext ) if ( str_ends_with ( lower ( source_file_path ), f_ext )) then source = parse_f_source ( source_file_path , error ) if ( source % unit_type == FPM_UNIT_PROGRAM ) then source % exe_name = basename ( source_file_path , suffix = . false .) end if else if ( str_ends_with ( lower ( source_file_path ), c_suffixes )) then source = parse_c_source ( source_file_path , error ) endif if ( allocated ( error )) then return end if end function parse_source !> List fortran suffixes, including optional ones subroutine list_fortran_suffixes ( suffixes , with_f_ext ) type ( string_t ), allocatable , intent ( out ) :: suffixes (:) !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) integer :: ndefault , nuser , i ndefault = size ( fortran_suffixes ) nuser = 0 ; if ( present ( with_f_ext )) nuser = size ( with_f_ext ) allocate ( suffixes ( ndefault + nuser )) do i = 1 , ndefault suffixes ( i ) = string_t ( fortran_suffixes ( i )) end do if ( present ( with_f_ext )) then do i = 1 , nuser suffixes ( ndefault + i ) = string_t ( with_f_ext ( i )% s ) end do endif end subroutine list_fortran_suffixes !> Add to `sources` by looking for source files in `directory` subroutine add_sources_from_dir ( sources , directory , scope , with_executables , with_f_ext , recurse , error ) !> List of `[[srcfile_t]]` objects to append to. Allocated if not allocated type ( srcfile_t ), allocatable , intent ( inout ), target :: sources (:) !> Directory in which to search for source files character ( * ), intent ( in ) :: directory !> Scope to apply to the discovered sources, see [[fpm_model]] for enumeration integer , intent ( in ) :: scope !> Executable sources (fortran `program`s) are ignored unless `with_executables=.true.` logical , intent ( in ), optional :: with_executables !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) !> Whether to recursively search subdirectories, default is `.true.` logical , intent ( in ), optional :: recurse !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i logical , allocatable :: is_source (:), exclude_source (:) logical :: recurse_ type ( string_t ), allocatable :: file_names (:) type ( string_t ), allocatable :: src_file_names (:), f_ext (:) type ( string_t ), allocatable :: existing_src_files (:) type ( srcfile_t ), allocatable :: dir_sources (:) recurse_ = . true . if ( present ( recurse )) recurse_ = recurse ! Scan directory for sources call list_files ( directory , file_names , recurse = recurse_ ) if ( allocated ( sources )) then allocate ( existing_src_files ( size ( sources ))) do i = 1 , size ( sources ) existing_src_files ( i )% s = canon_path ( sources ( i )% file_name ) end do else allocate ( existing_src_files ( 0 )) end if ! Get legal fortran suffixes call list_fortran_suffixes ( f_ext , with_f_ext ) is_source = [(. not .( is_hidden_file ( basename ( file_names ( i )% s ))) . and . & . not .( canon_path ( file_names ( i )% s ) . in . existing_src_files ) . and . & ( str_ends_with ( lower ( file_names ( i )% s ), f_ext ) . or . & str_ends_with ( lower ( file_names ( i )% s ), c_suffixes ) ), i = 1 , size ( file_names ))] src_file_names = pack ( file_names , is_source ) allocate ( dir_sources ( size ( src_file_names ))) allocate ( exclude_source ( size ( src_file_names ))) do i = 1 , size ( src_file_names ) dir_sources ( i ) = parse_source ( src_file_names ( i )% s , with_f_ext , error ) if ( allocated ( error )) return dir_sources ( i )% unit_scope = scope allocate ( dir_sources ( i )% link_libraries ( 0 )) ! Exclude executables unless specified otherwise exclude_source ( i ) = ( dir_sources ( i )% unit_type == FPM_UNIT_PROGRAM ) if ( dir_sources ( i )% unit_type == FPM_UNIT_PROGRAM . and . & & present ( with_executables )) then if ( with_executables ) then exclude_source ( i ) = . false . end if end if end do if (. not . allocated ( sources )) then sources = pack ( dir_sources ,. not . exclude_source ) else sources = [ sources , pack ( dir_sources ,. not . exclude_source )] end if end subroutine add_sources_from_dir !> Add to `sources` using the executable and test entries in the manifest and !> applies any executable-specific overrides such as `executable%name`. !> Adds all sources (including modules) from each `executable%source_dir` subroutine add_executable_sources ( sources , executables , scope , auto_discover , with_f_ext , error ) !> List of `[[srcfile_t]]` objects to append to. Allocated if not allocated type ( srcfile_t ), allocatable , intent ( inout ), target :: sources (:) !> List of `[[executable_config_t]]` entries from manifest class ( executable_config_t ), intent ( in ) :: executables (:) !> Scope to apply to the discovered sources: either `FPM_SCOPE_APP` or `FPM_SCOPE_TEST`, see [[fpm_model]] integer , intent ( in ) :: scope !> If `.false.` only executables and tests specified in the manifest are added to `sources` logical , intent ( in ) :: auto_discover !> Additional user-defined (preprocessor) extensions that should be treated as Fortran sources type ( string_t ), intent ( in ), optional :: with_f_ext (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j type ( string_t ), allocatable :: exe_dirs (:) type ( srcfile_t ) :: exe_source call get_executable_source_dirs ( exe_dirs , executables ) do i = 1 , size ( exe_dirs ) call add_sources_from_dir ( sources , exe_dirs ( i )% s , scope , & with_executables = auto_discover , with_f_ext = with_f_ext , recurse = . false ., error = error ) if ( allocated ( error )) then return end if end do exe_loop : do i = 1 , size ( executables ) ! Check if executable already discovered automatically ! and apply any overrides do j = 1 , size ( sources ) !> Compare lowercase strings to allow auto-discovery of pre-processed extensions if ( lower ( basename ( sources ( j )% file_name , suffix = . true .)) == lower ( executables ( i )% main ) . and .& canon_path ( dirname ( sources ( j )% file_name )) == & canon_path ( executables ( i )% source_dir ) ) then sources ( j )% exe_name = executables ( i )% name if ( allocated ( executables ( i )% link )) then sources ( j )% link_libraries = executables ( i )% link end if sources ( j )% unit_type = FPM_UNIT_PROGRAM cycle exe_loop end if end do ! Add if not already discovered (auto_discovery off) associate ( exe => executables ( i )) exe_source = parse_source ( join_path ( exe % source_dir , exe % main ), with_f_ext , error ) exe_source % exe_name = exe % name if ( allocated ( exe % link )) then exe_source % link_libraries = exe % link end if exe_source % unit_type = FPM_UNIT_PROGRAM exe_source % unit_scope = scope end associate if ( allocated ( error )) return if (. not . allocated ( sources )) then sources = [ exe_source ] else sources = [ sources , exe_source ] end if end do exe_loop end subroutine add_executable_sources !> Build a list of unique source directories !> from executables specified in manifest subroutine get_executable_source_dirs ( exe_dirs , executables ) type ( string_t ), allocatable , intent ( inout ) :: exe_dirs (:) class ( executable_config_t ), intent ( in ) :: executables (:) type ( string_t ) :: dirs_temp ( size ( executables )) integer :: i , n n = 0 do i = 1 , size ( executables ) dirs_temp ( i )% s = ' ' enddo do i = 1 , size ( executables ) if (. not .( executables ( i )% source_dir . in . dirs_temp )) then n = n + 1 dirs_temp ( n )% s = executables ( i )% source_dir end if end do if (. not . allocated ( exe_dirs )) then exe_dirs = dirs_temp ( 1 : n ) else exe_dirs = [ exe_dirs , dirs_temp ( 1 : n )] end if end subroutine get_executable_source_dirs !> Build an executable name with suffix. Safe routine that always returns an allocated string function get_exe_name_with_suffix ( source ) result ( suffixed ) type ( srcfile_t ), intent ( in ) :: source character ( len = :), allocatable :: suffixed if ( allocated ( source % exe_name )) then if ( get_os_type () == OS_WINDOWS ) then suffixed = source % exe_name // '.exe' else suffixed = source % exe_name end if else suffixed = \"\" endif end function get_exe_name_with_suffix end module fpm_sources","tags":"","loc":"sourcefile/fpm_sources.f90.html"},{"title":"fpm_command_line.f90 – Fortran-lang/fpm","text":"Source Code !># Definition of the command line interface !> !> This module uses [M_CLI2](https://github.com/urbanjost/M_CLI2) to define !> the command line interface. !> To define a command line interface create a new command settings type !> from the [[fpm_cmd_settings]] base class or the respective parent command !> settings. !> !> The subcommand is selected by the first non-option argument in the command !> line. In the subcase block the actual command line is defined and transferred !> to an instance of the [[fpm_cmd_settings]], the actual type is used by the !> *fpm* main program to determine which command entry point is chosen. !> !> To add a new subcommand add a new case to select construct and specify the !> wanted command line and the expected default values. !> Some of the following points also apply if you add a new option or argument !> to an existing *fpm* subcommand. !> At this point you should create a help page for the new command in a simple !> catman-like format as well in the ``set_help`` procedure. !> Make sure to register new subcommands in the ``fpm-manual`` command by adding !> them to the manual character array and in the help/manual case as well. !> You should add the new command to the synopsis section of the ``fpm-list``, !> ``fpm-help`` and ``fpm --list`` help pages below to make sure the help output !> is complete and consistent as well. module fpm_command_line use fpm_environment , only : get_os_type , get_env , & OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_WINDOWS , & OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD , OS_NAME use M_CLI2 , only : set_args , lget , sget , unnamed , remaining , specified use M_CLI2 , only : get_subcommand , CLI_RESPONSE_FILE use fpm_strings , only : lower , split , to_fortran_name , is_fortran_name , remove_characters_in_set , & string_t , glob use fpm_filesystem , only : basename , canon_path , which , run use fpm_environment , only : get_command_arguments_quoted use fpm_error , only : fpm_stop , error_t use fpm_os , only : get_current_directory use fpm_release , only : fpm_version , version_t use , intrinsic :: iso_fortran_env , only : stdin => input_unit , & & stdout => output_unit , & & stderr => error_unit implicit none private public :: fpm_cmd_settings , & fpm_build_settings , & fpm_install_settings , & fpm_export_settings , & fpm_new_settings , & fpm_run_settings , & fpm_test_settings , & fpm_update_settings , & fpm_clean_settings , & fpm_publish_settings , & get_command_line_settings , & get_fpm_env type , abstract :: fpm_cmd_settings character ( len = :), allocatable :: working_dir logical :: verbose = . true . end type integer , parameter :: ibug = 4096 type , extends ( fpm_cmd_settings ) :: fpm_new_settings character ( len = :), allocatable :: name logical :: with_executable = . false . logical :: with_test = . false . logical :: with_lib = . true . logical :: with_example = . false . logical :: with_full = . false . logical :: with_bare = . false . logical :: backfill = . true . end type type , extends ( fpm_cmd_settings ) :: fpm_build_settings logical :: list = . false . logical :: show_model = . false . logical :: build_tests = . false . logical :: prune = . true . character ( len = :), allocatable :: dump character ( len = :), allocatable :: compiler character ( len = :), allocatable :: c_compiler character ( len = :), allocatable :: cxx_compiler character ( len = :), allocatable :: archiver character ( len = :), allocatable :: profile character ( len = :), allocatable :: flag character ( len = :), allocatable :: cflag character ( len = :), allocatable :: cxxflag character ( len = :), allocatable :: ldflag end type type , extends ( fpm_build_settings ) :: fpm_run_settings character ( len = ibug ), allocatable :: name (:) character ( len = :), allocatable :: args ! passed to the app character ( len = :), allocatable :: runner character ( len = :), allocatable :: runner_args ! passed to the runner logical :: example contains procedure :: runner_command procedure :: name_ID end type type , extends ( fpm_run_settings ) :: fpm_test_settings end type type , extends ( fpm_build_settings ) :: fpm_install_settings character ( len = :), allocatable :: prefix character ( len = :), allocatable :: bindir character ( len = :), allocatable :: libdir character ( len = :), allocatable :: includedir logical :: no_rebuild end type !> Settings for interacting and updating with project dependencies type , extends ( fpm_cmd_settings ) :: fpm_update_settings character ( len = ibug ), allocatable :: name (:) character ( len = :), allocatable :: dump logical :: fetch_only logical :: clean end type !> Settings for exporting model data type , extends ( fpm_build_settings ) :: fpm_export_settings character ( len = :), allocatable :: dump_manifest character ( len = :), allocatable :: dump_dependencies character ( len = :), allocatable :: dump_model end type type , extends ( fpm_cmd_settings ) :: fpm_clean_settings logical :: clean_skip = . false . logical :: clean_all = . false . logical :: registry_cache = . false . end type type , extends ( fpm_build_settings ) :: fpm_publish_settings logical :: show_package_version = . false . logical :: show_upload_data = . false . logical :: is_dry_run = . false . character ( len = :), allocatable :: token end type character ( len = :), allocatable :: name character ( len = :), allocatable :: os_type character ( len = ibug ), allocatable :: names (:) character ( len = :), allocatable :: tnames (:) character ( len = :), allocatable :: version_text (:) character ( len = :), allocatable :: help_new (:), help_fpm (:), help_run (:), & & help_test (:), help_build (:), help_usage (:), help_runner (:), & & help_text (:), help_install (:), help_help (:), help_update (:), & & help_list (:), help_list_dash (:), help_list_nodash (:), & & help_clean (:), help_publish (:) character ( len = 20 ), parameter :: manual ( * ) = [ character ( len = 20 ) :: & & ' ' , 'fpm' , 'new' , 'build' , 'run' , 'clean' , & & 'test' , 'runner' , 'install' , 'update' , 'list' , 'help' , 'version' , 'publish' ] character ( len = :), allocatable :: val_runner , val_compiler , val_flag , val_cflag , val_cxxflag , val_ldflag , & val_profile , val_runner_args , val_dump ! '12345678901234567890123456789012345678901234567890123456789012345678901234567890',& character ( len = 80 ), parameter :: help_text_build_common ( * ) = [ character ( len = 80 ) :: & ' --profile PROF Selects the compilation profile for the build. ' ,& ' Currently available profiles are \"release\" for ' ,& ' high optimization and \"debug\" for full debug options. ' ,& ' If --flag is not specified the \"debug\" flags are the ' ,& ' default. ' ,& ' --no-prune Disable tree-shaking/pruning of unused module dependencies ' & ] ! '12345678901234567890123456789012345678901234567890123456789012345678901234567890',& character ( len = 80 ), parameter :: help_text_compiler ( * ) = [ character ( len = 80 ) :: & ' --compiler NAME Specify a compiler name. The default is \"gfortran\" ' ,& ' unless set by the environment variable FPM_FC. ' ,& ' --c-compiler NAME Specify the C compiler name. Automatically determined by ' ,& ' default unless set by the environment variable FPM_CC. ' ,& ' --cxx-compiler NAME Specify the C++ compiler name. Automatically determined by' ,& ' default unless set by the environment variable FPM_CXX. ' ,& ' --archiver NAME Specify the archiver name. Automatically determined by ' ,& ' default unless set by the environment variable FPM_AR. ' & ] ! '12345678901234567890123456789012345678901234567890123456789012345678901234567890',& character ( len = 80 ), parameter :: help_text_flag ( * ) = [ character ( len = 80 ) :: & ' --flag FFLAGS selects compile arguments for the build, the default value is' ,& ' set by the FPM_FFLAGS environment variable. These are added ' ,& ' to the profile options if --profile is specified, else these ' ,& ' are added to the defaults. To override the defaults, use the ' ,& ' keyword [fortran] in the manifest. Note object and .mod ' ,& ' directory locations are always built in. ' ,& ' --c-flag CFLAGS selects compile arguments specific for C source in the build.' ,& ' The default value is set by the FPM_CFLAGS environment ' ,& ' variable. ' ,& ' --cxx-flag CFLAGS selects compile arguments specific for C++ source in the ' ,& ' build. The default value is set by the FPM_CXXFLAGS ' ,& ' environment variable. ' ,& ' --link-flag LDFLAGS select arguments passed to the linker for the build. The ' ,& ' default value is set by the FPM_LDFLAGS environment variable.' & ] character ( len = 80 ), parameter :: help_text_environment ( * ) = [ character ( len = 80 ) :: & 'ENVIRONMENT VARIABLES' ,& ' FPM_FC sets the path to the Fortran compiler used for the build,' , & ' will be overwritten by --compiler command line option' , & '' , & ' FPM_FFLAGS sets the arguments for the Fortran compiler' , & ' will be overwritten by --flag command line option' , & '' , & ' FPM_CC sets the path to the C compiler used for the build,' , & ' will be overwritten by --c-compiler command line option' , & '' , & ' FPM_CFLAGS sets the arguments for the C compiler' , & ' will be overwritten by --c-flag command line option' , & '' , & ' FPM_CXX sets the path to the C++ compiler used for the build,' , & ' will be overwritten by --cxx-compiler command line option' , & '' , & ' FPM_CXXFLAGS sets the arguments for the C++ compiler' , & ' will be overwritten by --cxx-flag command line option' , & '' , & ' FPM_AR sets the path to the archiver used for the build,' , & ' will be overwritten by --archiver command line option' , & '' , & ' FPM_LDFLAGS sets additional link arguments for creating executables' , & ' will be overwritten by --link-flag command line option' & ] contains subroutine get_command_line_settings ( cmd_settings ) class ( fpm_cmd_settings ), allocatable , intent ( out ) :: cmd_settings integer , parameter :: widest = 256 character ( len = 4096 ) :: cmdarg integer :: i integer :: os type ( fpm_install_settings ), allocatable :: install_settings type ( fpm_publish_settings ), allocatable :: publish_settings type ( fpm_export_settings ) , allocatable :: export_settings type ( version_t ) :: version character ( len = :), allocatable :: common_args , compiler_args , run_args , working_dir , & & c_compiler , cxx_compiler , archiver , version_s , token_s character ( len =* ), parameter :: fc_env = \"FC\" , cc_env = \"CC\" , ar_env = \"AR\" , & & fflags_env = \"FFLAGS\" , cflags_env = \"CFLAGS\" , cxxflags_env = \"CXXFLAGS\" , ldflags_env = \"LDFLAGS\" , & & fc_default = \"gfortran\" , cc_default = \" \" , ar_default = \" \" , flags_default = \" \" , & & cxx_env = \"CXX\" , cxx_default = \" \" type ( error_t ), allocatable :: error call set_help () os = get_os_type () ! text for --version switch, select case ( os ) case ( OS_LINUX ); os_type = \"OS Type: Linux\" case ( OS_MACOS ); os_type = \"OS Type: macOS\" case ( OS_WINDOWS ); os_type = \"OS Type: Windows\" case ( OS_CYGWIN ); os_type = \"OS Type: Cygwin\" case ( OS_SOLARIS ); os_type = \"OS Type: Solaris\" case ( OS_FREEBSD ); os_type = \"OS Type: FreeBSD\" case ( OS_OPENBSD ); os_type = \"OS Type: OpenBSD\" case ( OS_UNKNOWN ); os_type = \"OS Type: Unknown\" case default ; os_type = \"OS Type: UNKNOWN\" end select ! Get current release version version = fpm_version () version_s = version % s () version_text = [ character ( len = 80 ) :: & & 'Version: ' // trim ( version_s ) // ', alpha' , & & 'Program: fpm(1)' , & & 'Description: A Fortran package manager and build system' , & & 'Home Page: https://github.com/fortran-lang/fpm' , & & 'License: MIT' , & & os_type ] ! find the subcommand name by looking for first word on command ! not starting with dash CLI_RESPONSE_FILE = . true . cmdarg = get_subcommand () common_args = & ' --directory:C \" \"' // & ' --verbose F' run_args = & ' --target \" \"' // & ' --list F' // & ' --runner \" \"' // & ' --runner-args \" \"' compiler_args = & ' --profile \" \"' // & ' --no-prune F' // & ' --compiler \"' // get_fpm_env ( fc_env , fc_default ) // '\"' // & ' --c-compiler \"' // get_fpm_env ( cc_env , cc_default ) // '\"' // & ' --cxx-compiler \"' // get_fpm_env ( cxx_env , cxx_default ) // '\"' // & ' --archiver \"' // get_fpm_env ( ar_env , ar_default ) // '\"' // & ' --flag:: \"' // get_fpm_env ( fflags_env , flags_default ) // '\"' // & ' --c-flag:: \"' // get_fpm_env ( cflags_env , flags_default ) // '\"' // & ' --cxx-flag:: \"' // get_fpm_env ( cxxflags_env , flags_default ) // '\"' // & ' --link-flag:: \"' // get_fpm_env ( ldflags_env , flags_default ) // '\"' ! now set subcommand-specific help text and process commandline ! arguments. Then call subcommand routine select case ( trim ( cmdarg )) case ( 'run' ) call set_args ( common_args // compiler_args // run_args // '& & --all F & & --example F& & --' , help_run , version_text ) call check_build_vals () if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif if ( specified ( 'target' ) ) then call split ( sget ( 'target' ), tnames , delimiters = ' ,:' ) names = [ character ( len = max ( len ( names ), len ( tnames ))) :: names , tnames ] endif ! convert --all to '*' if ( lget ( 'all' )) then names = [ character ( len = max ( len ( names ), 1 )) :: names , '*' ] endif ! convert special string '..' to equivalent (shorter) '*' ! to allow for a string that does not require shift-key and quoting do i = 1 , size ( names ) if ( names ( i ) == '..' ) names ( i ) = '*' enddo ! If there are additional command-line arguments, remove the additional ! double quotes which have been added by M_CLI2 val_runner_args = sget ( 'runner-args' ) call remove_characters_in_set ( val_runner_args , set = '\"' ) c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( fpm_run_settings :: cmd_settings ) val_runner = sget ( 'runner' ) if ( specified ( 'runner' ) . and . val_runner == '' ) val_runner = 'echo' cmd_settings = fpm_run_settings (& & args = remaining ,& & profile = val_profile ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & example = lget ( 'example' ), & & list = lget ( 'list' ),& & build_tests = . false .,& & name = names ,& & runner = val_runner ,& & runner_args = val_runner_args , & & verbose = lget ( 'verbose' ) ) case ( 'build' ) call set_args ( common_args // compiler_args // '& & --list F & & --show-model F & & --dump \" \" & & --tests F & & --' , help_build , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) val_dump = sget ( 'dump' ) if ( specified ( 'dump' ) . and . val_dump == '' ) val_dump = 'fpm_model.toml' allocate ( fpm_build_settings :: cmd_settings ) cmd_settings = fpm_build_settings ( & & profile = val_profile ,& & dump = val_dump ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & list = lget ( 'list' ),& & show_model = lget ( 'show-model' ),& & build_tests = lget ( 'tests' ),& & verbose = lget ( 'verbose' ) ) case ( 'new' ) call set_args ( common_args // '& & --src F & & --lib F & & --app F & & --test F & & --example F & & --backfill F & & --full F & & --bare F' , & & help_new , version_text ) select case ( size ( unnamed )) case ( 1 ) if ( lget ( 'backfill' )) then name = '.' else write ( stderr , '(*(7x,g0,/))' ) & & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]|[--full|--bare] [--backfill]' call fpm_stop ( 1 , 'directory name required' ) endif case ( 2 ) name = trim ( unnamed ( 2 )) case default write ( stderr , '(7x,g0)' ) & & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]| [--full|--bare] [--backfill]' call fpm_stop ( 2 , 'only one directory name allowed' ) end select !*! canon_path is not converting \".\", etc. if ( name == '.' ) then call get_current_directory ( name , error ) if ( allocated ( error )) then write ( stderr , '(\"[Error]\", 1x, a)' ) error % message stop 1 endif endif name = canon_path ( name ) if ( . not . is_fortran_name ( to_fortran_name ( basename ( name ))) ) then write ( stderr , '(g0)' ) [ character ( len = 72 ) :: & & ' the fpm project name must be made of up to 63 ASCII letters,' , & & ' numbers, underscores, or hyphens, and start with a letter.' ] call fpm_stop ( 4 , ' ' ) endif allocate ( fpm_new_settings :: cmd_settings ) if ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' , 'bare' ])) & & . and . lget ( 'full' ) ) then write ( stderr , '(*(a))' )& & ' --full and any of [--src|--lib,--app,--test,--example,--bare]' , & & ' are mutually exclusive.' call fpm_stop ( 5 , ' ' ) elseif ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' , 'full' ])) & & . and . lget ( 'bare' ) ) then write ( stderr , '(*(a))' )& & ' --bare and any of [--src|--lib,--app,--test,--example,--full]' , & & ' are mutually exclusive.' call fpm_stop ( 3 , ' ' ) elseif ( any ( specified ([ character ( len = 10 ) :: 'src' , 'lib' , 'app' , 'test' , 'example' ]) ) ) then cmd_settings = fpm_new_settings (& & backfill = lget ( 'backfill' ), & & name = name , & & with_executable = lget ( 'app' ), & & with_lib = any ([ lget ( 'lib' ), lget ( 'src' )]), & & with_test = lget ( 'test' ), & & with_example = lget ( 'example' ), & & verbose = lget ( 'verbose' ) ) else ! default if no specific directories are requested cmd_settings = fpm_new_settings (& & backfill = lget ( 'backfill' ) , & & name = name , & & with_executable = . true ., & & with_lib = . true ., & & with_test = . true ., & & with_example = lget ( 'full' ), & & with_full = lget ( 'full' ), & & with_bare = lget ( 'bare' ), & & verbose = lget ( 'verbose' ) ) endif case ( 'help' , 'manual' ) call set_args ( common_args , help_help , version_text ) if ( size ( unnamed ) < 2 ) then if ( unnamed ( 1 ) == 'help' ) then unnamed = [ ' ' , 'fpm' ] else unnamed = manual endif elseif ( unnamed ( 2 ) == 'manual' ) then unnamed = manual endif allocate ( character ( len = widest ) :: help_text ( 0 )) do i = 2 , size ( unnamed ) select case ( unnamed ( i )) case ( ' ' ) case ( 'fpm ' ) help_text = [ character ( len = widest ) :: help_text , help_fpm ] case ( 'new ' ) help_text = [ character ( len = widest ) :: help_text , help_new ] case ( 'build ' ) help_text = [ character ( len = widest ) :: help_text , help_build ] case ( 'install' ) help_text = [ character ( len = widest ) :: help_text , help_install ] case ( 'run ' ) help_text = [ character ( len = widest ) :: help_text , help_run ] case ( 'test ' ) help_text = [ character ( len = widest ) :: help_text , help_test ] case ( 'runner' ) help_text = [ character ( len = widest ) :: help_text , help_runner ] case ( 'list ' ) help_text = [ character ( len = widest ) :: help_text , help_list ] case ( 'update ' ) help_text = [ character ( len = widest ) :: help_text , help_update ] case ( 'help ' ) help_text = [ character ( len = widest ) :: help_text , help_help ] case ( 'version' ) help_text = [ character ( len = widest ) :: help_text , version_text ] case ( 'clean' ) help_text = [ character ( len = widest ) :: help_text , help_clean ] case ( 'publish' ) help_text = [ character ( len = widest ) :: help_text , help_publish ] case default help_text = [ character ( len = widest ) :: help_text , & & ' unknown help topic \"' // trim ( unnamed ( i )) // '\"' ] !!& ' unknown help topic \"'//trim(unnamed(i)).'not found in:',manual] end select enddo call printhelp ( help_text ) case ( 'install' ) call set_args ( common_args // compiler_args // '& & --no-rebuild F --prefix \" \" & & --list F & & --libdir \"lib\" --bindir \"bin\" --includedir \"include\"' , & help_install , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( install_settings , source = fpm_install_settings (& list = lget ( 'list' ), & profile = val_profile ,& prune = . not . lget ( 'no-prune' ), & compiler = val_compiler , & c_compiler = c_compiler , & cxx_compiler = cxx_compiler , & archiver = archiver , & flag = val_flag , & cflag = val_cflag , & cxxflag = val_cxxflag , & ldflag = val_ldflag , & no_rebuild = lget ( 'no-rebuild' ), & verbose = lget ( 'verbose' ))) call get_char_arg ( install_settings % prefix , 'prefix' ) call get_char_arg ( install_settings % libdir , 'libdir' ) call get_char_arg ( install_settings % bindir , 'bindir' ) call get_char_arg ( install_settings % includedir , 'includedir' ) call move_alloc ( install_settings , cmd_settings ) case ( 'list' ) call set_args ( common_args // '& & --list F& &' , help_list , version_text ) if ( lget ( 'list' )) then help_text = [ character ( widest ) :: help_list_nodash , help_list_dash ] else help_text = help_list_nodash endif call printhelp ( help_text ) case ( 'test' ) call set_args ( common_args // compiler_args // run_args // ' --' , & help_test , version_text ) call check_build_vals () if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif if ( specified ( 'target' ) ) then call split ( sget ( 'target' ), tnames , delimiters = ' ,:' ) names = [ character ( len = max ( len ( names ), len ( tnames ))) :: names , tnames ] endif ! convert special string '..' to equivalent (shorter) '*' ! to allow for a string that does not require shift-key and quoting do i = 1 , size ( names ) if ( names ( i ) == '..' ) names ( i ) = '*' enddo ! If there are additional command-line arguments, remove the additional ! double quotes which have been added by M_CLI2 val_runner_args = sget ( 'runner-args' ) call remove_characters_in_set ( val_runner_args , set = '\"' ) c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( fpm_test_settings :: cmd_settings ) val_runner = sget ( 'runner' ) if ( specified ( 'runner' ) . and . val_runner == '' ) val_runner = 'echo' cmd_settings = fpm_test_settings (& & args = remaining , & & profile = val_profile , & & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & example = . false ., & & list = lget ( 'list' ), & & build_tests = . true ., & & name = names , & & runner = val_runner , & & runner_args = val_runner_args , & & verbose = lget ( 'verbose' )) case ( 'update' ) call set_args ( common_args // ' --fetch-only F --clean F --dump \" \" ' , & help_update , version_text ) if ( size ( unnamed ) > 1 ) then names = unnamed ( 2 :) else names = [ character ( len = len ( names )) :: ] endif val_dump = sget ( 'dump' ) if ( specified ( 'dump' ) . and . val_dump == '' ) val_dump = 'fpm_dependencies.toml' allocate ( fpm_update_settings :: cmd_settings ) cmd_settings = fpm_update_settings ( name = names , dump = val_dump , & fetch_only = lget ( 'fetch-only' ), verbose = lget ( 'verbose' ), & clean = lget ( 'clean' )) case ( 'export' ) call set_args ( common_args // compiler_args // '& & --manifest \"filename\" & & --model \"filename\" & & --dependencies \"filename\" ' , & help_build , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) allocate ( export_settings , source = fpm_export_settings (& profile = val_profile ,& prune = . not . lget ( 'no-prune' ), & compiler = val_compiler , & c_compiler = c_compiler , & cxx_compiler = cxx_compiler , & archiver = archiver , & flag = val_flag , & cflag = val_cflag , & show_model = . true ., & cxxflag = val_cxxflag , & ldflag = val_ldflag , & verbose = lget ( 'verbose' ))) call get_char_arg ( export_settings % dump_model , 'model' ) call get_char_arg ( export_settings % dump_manifest , 'manifest' ) call get_char_arg ( export_settings % dump_dependencies , 'dependencies' ) call move_alloc ( export_settings , cmd_settings ) case ( 'clean' ) call set_args ( common_args // & & ' --registry-cache' // & & ' --skip' // & & ' --all' , & help_clean , version_text ) block logical :: skip , clean_all skip = lget ( 'skip' ) clean_all = lget ( 'all' ) if ( all ([ skip , clean_all ])) then call fpm_stop ( 6 , 'Do not specify both --skip and --all options on the clean subcommand.' ) end if allocate ( fpm_clean_settings :: cmd_settings ) cmd_settings = fpm_clean_settings ( & & registry_cache = lget ( 'registry-cache' ), & & clean_skip = skip , & & clean_all = clean_all ) end block case ( 'publish' ) call set_args ( common_args // compiler_args // '& & --show-package-version F & & --show-upload-data F & & --dry-run F & & --token \" \" & & --list F & & --show-model F & & --tests F & & --' , help_publish , version_text ) call check_build_vals () c_compiler = sget ( 'c-compiler' ) cxx_compiler = sget ( 'cxx-compiler' ) archiver = sget ( 'archiver' ) token_s = sget ( 'token' ) allocate ( fpm_publish_settings :: cmd_settings ) cmd_settings = fpm_publish_settings ( & & show_package_version = lget ( 'show-package-version' ), & & show_upload_data = lget ( 'show-upload-data' ), & & is_dry_run = lget ( 'dry-run' ), & & profile = val_profile ,& & prune = . not . lget ( 'no-prune' ), & & compiler = val_compiler , & & c_compiler = c_compiler , & & cxx_compiler = cxx_compiler , & & archiver = archiver , & & flag = val_flag , & & cflag = val_cflag , & & cxxflag = val_cxxflag , & & ldflag = val_ldflag , & & list = lget ( 'list' ),& & show_model = lget ( 'show-model' ),& & build_tests = lget ( 'tests' ),& & verbose = lget ( 'verbose' ),& & token = token_s ) case default if ( cmdarg . ne . '' . and . which ( 'fpm-' // cmdarg ). ne . '' ) then call run ( 'fpm-' // trim ( cmdarg ) // ' ' // get_command_arguments_quoted (),. false .) stop else call set_args ( '& & --list F& &' , help_fpm , version_text ) ! Note: will not get here if --version or --usage or --help ! is present on commandline if ( lget ( 'list' )) then help_text = help_list_dash elseif ( len_trim ( cmdarg ) == 0 ) then write ( stdout , '(*(a))' ) 'Fortran Package Manager:' write ( stdout , '(*(a))' ) ' ' help_text = [ character ( widest ) :: help_list_nodash , help_usage ] else write ( stderr , '(*(a))' ) ' unknown subcommand [' , & & trim ( cmdarg ), ']' help_text = [ character ( widest ) :: help_list_dash , help_usage ] endif call printhelp ( help_text ) endif end select if ( allocated ( cmd_settings )) then working_dir = sget ( \"directory\" ) call move_alloc ( working_dir , cmd_settings % working_dir ) end if contains subroutine check_build_vals () val_compiler = sget ( 'compiler' ) if ( val_compiler == '' ) val_compiler = 'gfortran' val_flag = \" \" // sget ( 'flag' ) val_cflag = \" \" // sget ( 'c-flag' ) val_cxxflag = \" \" // sget ( 'cxx-flag' ) val_ldflag = \" \" // sget ( 'link-flag' ) val_profile = sget ( 'profile' ) end subroutine check_build_vals !> Print help text and stop subroutine printhelp ( lines ) character ( len = :), intent ( in ), allocatable :: lines (:) integer :: iii , ii if ( allocated ( lines )) then ii = size ( lines ) if ( ii > 0 . and . len ( lines ) > 0 ) then write ( stdout , '(g0)' )( trim ( lines ( iii )), iii = 1 , ii ) else write ( stdout , '(a)' ) ' *printhelp* output requested is empty' endif endif stop end subroutine printhelp end subroutine get_command_line_settings subroutine set_help () help_list_nodash = [ character ( len = 80 ) :: & 'USAGE: fpm [ SUBCOMMAND [SUBCOMMAND_OPTIONS] ]|[--list|--help|--version]' , & ' where SUBCOMMAND is commonly new|build|run|test ' , & ' ' , & ' subcommand may be one of ' , & ' ' , & ' build Compile the package placing results in the \"build\" directory' , & ' help Display help ' , & ' list Display this list of subcommand descriptions ' , & ' new Create a new Fortran package directory with sample files ' , & ' run Run the local package application programs ' , & ' test Run the test programs ' , & ' update Update and manage project dependencies ' , & ' install Install project ' , & ' clean Delete the build ' , & ' publish Publish package to the registry ' , & ' ' , & ' Enter \"fpm --list\" for a brief list of subcommand options. Enter ' , & ' \"fpm --help\" or \"fpm SUBCOMMAND --help\" for detailed descriptions. ' , & ' ' ] help_list_dash = [ character ( len = 80 ) :: & ' ' , & ' build [--compiler COMPILER_NAME] [--profile PROF] [--flag FFLAGS] [--list] ' , & ' [--tests] [--no-prune] [--dump [FILENAME]] ' , & ' help [NAME(s)] ' , & ' new NAME [[--lib|--src] [--app] [--test] [--example]]| ' , & ' [--full|--bare][--backfill] ' , & ' update [NAME(s)] [--fetch-only] [--clean] [--verbose] [--dump [FILENAME]] ' , & ' list [--list] ' , & ' run [[--target] NAME(s) [--example] [--profile PROF] [--flag FFLAGS] [--all] ' , & ' [--runner \"CMD\"] [--compiler COMPILER_NAME] [--list] [-- ARGS] ' , & ' test [[--target] NAME(s)] [--profile PROF] [--flag FFLAGS] [--runner \"CMD\"] ' , & ' [--list] [--compiler COMPILER_NAME] [-- ARGS] ' , & ' install [--profile PROF] [--flag FFLAGS] [--no-rebuild] [--prefix PATH] ' , & ' [options] ' , & ' clean [--skip] [--all] [--registry-cache] ' , & ' publish [--token TOKEN] [--show-package-version] [--show-upload-data] ' , & ' [--dry-run] [--verbose] ' , & ' ' ] help_usage = [ character ( len = 80 ) :: & '' ] help_runner = [ character ( len = 80 ) :: & 'NAME ' , & ' --runner(1) - a shared option for specifying an application to launch ' , & ' executables. ' , & ' ' , & 'SYNOPSIS ' , & ' fpm run|test --runner CMD ... --runner-args ARGS -- SUFFIX_OPTIONS ' , & ' ' , & 'DESCRIPTION ' , & ' The --runner option allows specifying a program to launch ' , & ' executables selected via the fpm(1) subcommands \"run\" and \"test\". This ' , & ' gives easy recourse to utilities such as debuggers and other tools ' , & ' that wrap other executables. ' , & ' ' , & ' These external commands are not part of fpm(1) itself as they vary ' , & ' from platform to platform or require independent installation. ' , & ' ' , & 'OPTION ' , & ' --runner ''CMD'' quoted command used to launch the fpm(1) executables. ' , & ' Available for both the \"run\" and \"test\" subcommands. ' , & ' If the keyword is specified without a value the default command ' , & ' is \"echo\". ' , & ' --runner-args \"args\" an additional option to pass command-line arguments ' , & ' to the runner command, instead of to the fpm app. ' , & ' -- SUFFIX_OPTIONS additional options to suffix the command CMD and executable ' , & ' file names with. These options are passed as command-line ' , & ' arguments to the app. ' , & 'EXAMPLES ' , & ' Use cases for ''fpm run|test --runner \"CMD\"'' include employing ' , & ' the following common GNU/Linux and Unix commands: ' , & ' ' , & ' INTERROGATE ' , & ' + nm - list symbols from object files ' , & ' + size - list section sizes and total size. ' , & ' + ldd - print shared object dependencies ' , & ' + ls - list directory contents ' , & ' + stat - display file or file system status ' , & ' + file - determine file type ' , & ' PERFORMANCE AND DEBUGGING ' , & ' + gdb - The GNU Debugger ' , & ' + valgrind - a suite of tools for debugging and profiling ' , & ' + time - time a simple command or give resource usage ' , & ' + timeout - run a command with a time limit ' , & ' COPY ' , & ' + install - copy files and set attributes ' , & ' + tar - an archiving utility ' , & ' ALTER ' , & ' + rm - remove files or directories ' , & ' + chmod - change permissions of a file ' , & ' + strip - remove unnecessary information from strippable files ' , & ' ' , & ' For example ' , & ' ' , & ' fpm test --runner gdb ' , & ' fpm run --runner \"tar cvfz $HOME/bundle.tgz\" ' , & ' fpm run --runner \"mpiexec\" --runner-args \"-np 12\" ' , & ' fpm run --runner ldd ' , & ' fpm run --runner strip ' , & ' fpm run --runner ''cp -t /usr/local/bin'' ' , & ' ' , & ' # options after executable name can be specified after the -- option ' , & ' fpm --runner cp run -- /usr/local/bin/ ' , & ' # generates commands of the form \"cp $FILENAME /usr/local/bin/\" ' , & ' ' , & ' # bash(1) alias example: ' , & ' alias fpm-install=\\ ' , & ' \"fpm run --profile release --runner ''install -vbp -m 0711 -t ~/.local/bin''\" ' , & ' fpm-install ' , & '' ] help_fpm = [ character ( len = 80 ) :: & 'NAME ' , & ' fpm(1) - A Fortran package manager and build system ' , & ' ' , & 'SYNOPSIS ' , & ' fpm SUBCOMMAND [SUBCOMMAND_OPTIONS] ' , & ' ' , & ' fpm --help|--version|--list ' , & ' ' , & 'DESCRIPTION ' , & ' fpm(1) is a package manager that helps you create Fortran projects ' , & ' from source -- it automatically determines dependencies! ' , & ' ' , & ' Most significantly fpm(1) lets you draw upon other fpm(1) packages ' , & ' in distributed git(1) repositories as if the packages were a basic ' , & ' part of your default programming environment, as well as letting ' , & ' you share your projects with others in a similar manner. ' , & ' ' , & ' All output goes into the directory \"build/\" which can generally be ' , & ' removed and rebuilt if required. Note that if external packages are ' , & ' being used you need network connectivity to rebuild from scratch. ' , & ' ' , & 'SUBCOMMANDS ' , & ' Valid fpm(1) subcommands are: ' , & ' ' , & ' + build Compile the packages into the \"build/\" directory. ' , & ' + new Create a new Fortran package directory with sample files. ' , & ' + update Update the project dependencies. ' , & ' + run Run the local package binaries. Defaults to all binaries ' , & ' for that release. ' , & ' + test Run the tests. ' , & ' + help Alternate to the --help switch for displaying help text. ' , & ' + list Display brief descriptions of all subcommands. ' , & ' + install Install project. ' , & ' + clean Delete directories in the \"build/\" directory, except ' , & ' dependencies. Prompts for confirmation to delete. ' , & ' + publish Publish package to the registry. ' , & ' ' , & ' Their syntax is ' , & ' ' , & ' build [--profile PROF] [--flag FFLAGS] [--list] [--compiler COMPILER_NAME] ' , & ' [--tests] [--no-prune] [--dump [FILENAME]] ' , & ' new NAME [[--lib|--src] [--app] [--test] [--example]]| ' , & ' [--full|--bare][--backfill] ' , & ' update [NAME(s)] [--fetch-only] [--clean] [--dump [FILENAME]] ' , & ' run [[--target] NAME(s)] [--profile PROF] [--flag FFLAGS] [--list] [--all] ' , & ' [--example] [--runner \"CMD\"] [--compiler COMPILER_NAME] ' , & ' [--no-prune] [-- ARGS] ' , & ' test [[--target] NAME(s)] [--profile PROF] [--flag FFLAGS] [--list] ' , & ' [--runner \"CMD\"] [--compiler COMPILER_NAME] [--no-prune] [-- ARGS] ' , & ' help [NAME(s)] ' , & ' list [--list] ' , & ' install [--profile PROF] [--flag FFLAGS] [--no-rebuild] [--prefix PATH] ' , & ' [options] ' , & ' clean [--skip] [--all] [--registry-cache] ' , & ' publish [--token TOKEN] [--show-package-version] [--show-upload-data] ' , & ' [--dry-run] [--verbose] ' , & ' ' , & 'SUBCOMMAND OPTIONS ' , & ' -C, --directory PATH' , & ' Change working directory to PATH before running any command' , & help_text_build_common , & help_text_compiler , & help_text_flag , & ' --list List candidates instead of building or running them. On ' , & ' the fpm(1) command this shows a brief list of subcommands.' , & ' --runner CMD Provides a command to prefix program execution paths. ' , & ' -- ARGS Arguments to pass to executables. ' , & ' --skip Delete directories in the build/ directory without ' , & ' prompting, but skip dependencies. Cannot be used together ' , & ' with --all. ' , & ' --all Delete directories in the build/ directory without ' , & ' prompting, including dependencies. Cannot be used together' , & ' with --skip. ' , & ' --registry-cache Delete registry cache. ' , & ' ' , & 'VALID FOR ALL SUBCOMMANDS ' , & ' --help Show help text and exit ' , & ' --verbose Display additional information when available ' , & ' --version Show version information and exit. ' , & ' ' , & '@file ' , & ' You may replace the default options for the fpm(1) command from a ' , & ' file if your first options begin with @file. Initial options will ' , & ' then be read from the \"response file\" \"file.rsp\" in the current ' , & ' directory. ' , & ' ' , & ' If \"file\" does not exist or cannot be read, then an error occurs and' , & ' the program stops. Each line of the file is prefixed with \"options\" ' , & ' and interpreted as a separate argument. The file itself may not ' , & ' contain @file arguments. That is, it is not processed recursively. ' , & ' ' , & ' For more information on response files see ' , & ' ' , & ' https://urbanjost.github.io/M_CLI2/set_args.3m_cli2.html ' , & ' ' , & ' The basic functionality described here will remain the same, but ' , & ' other features described at the above reference may change. ' , & ' ' , & ' An example file: ' , & ' ' , & ' # my build options ' , & ' options build ' , & ' options --compiler gfortran ' , & ' options --flag \"-pg -static -pthread -Wunreachable-code -Wunused ' , & ' -Wuninitialized -g -O -fbacktrace -fdump-core -fno-underscoring ' , & ' -frecord-marker=4 -L/usr/X11R6/lib -L/usr/X11R6/lib64 -lX11\" ' , & ' ' , & ' Note --flag would have to be on one line as response files do not ' , & ' (currently) allow for continued lines or multiple specifications of ' , & ' the same option. ' , & ' ' , & help_text_environment , & ' ' , & 'EXAMPLES ' , & ' sample commands: ' , & ' ' , & ' fpm new mypackage --app --test ' , & ' fpm build ' , & ' fpm test ' , & ' fpm run ' , & ' fpm run --example ' , & ' fpm new --help ' , & ' fpm run myprogram --profile release -- -x 10 -y 20 --title \"my title\" ' , & ' fpm install --prefix ~/.local ' , & ' fpm clean --all ' , & ' ' , & 'SEE ALSO ' , & ' ' , & ' + The fpm(1) home page is at https://github.com/fortran-lang/fpm ' , & ' + Registered fpm(1) packages are at https://fortran-lang.org/packages ' , & ' + The fpm(1) TOML file format is described at ' , & ' https://fpm.fortran-lang.org/spec/manifest.html ' , & '' ] help_list = [ character ( len = 80 ) :: & 'NAME ' , & ' list(1) - list summary of fpm(1) subcommands ' , & ' ' , & 'SYNOPSIS ' , & ' fpm list ' , & ' ' , & ' fpm list --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' Display a short description for each fpm(1) subcommand. ' , & ' ' , & 'OPTIONS ' , & ' --list display a list of command options as well. This is the ' , & ' same output as generated by \"fpm --list\". ' , & ' ' , & 'EXAMPLES ' , & ' display a short list of fpm(1) subcommands ' , & ' ' , & ' fpm list ' , & ' fpm --list ' , & '' ] help_run = [ character ( len = 80 ) :: & 'NAME ' , & ' run(1) - the fpm(1) subcommand to run project applications ' , & ' ' , & 'SYNOPSIS ' , & ' fpm run [[--target] NAME(s) [--profile PROF] [--flag FFLAGS]' , & ' [--compiler COMPILER_NAME] [--runner \"CMD\"] [--example]' , & ' [--list] [--all] [-- ARGS]' , & ' ' , & ' fpm run --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' Run the applications in your fpm(1) package. By default applications ' , & ' in /app or specified as \"executable\" in your \"fpm.toml\" manifest are ' , & ' used. Alternatively demonstration programs in example/ or specified in' , & ' the \"example\" section in \"fpm.toml\" can be executed. The applications ' , & ' are automatically rebuilt before being run if they are out of date. ' , & ' ' , & 'OPTIONS ' , & ' --target NAME(s) list of application names to execute. No name is ' , & ' required if only one target exists. If no name is ' , & ' supplied and more than one candidate exists or a ' , & ' name has no match a list is produced and fpm(1) ' , & ' exits. ' , & ' ' , & ' Basic \"globbing\" is supported where \"?\" represents ' , & ' any single character and \"*\" represents any string. ' , & ' Note The glob string normally needs quoted to ' , & ' the special characters from shell expansion. ' , & ' --all Run all examples or applications. An alias for --target ''*''. ' , & ' --example Run example programs instead of applications. ' , & help_text_build_common , & help_text_compiler , & help_text_flag , & ' --runner CMD A command to prefix the program execution paths with. ' , & ' see \"fpm help runner\" for further details. ' , & ' --list list basenames of candidates instead of running them. Note ' , & ' out-of-date candidates will still be rebuilt before being ' , & ' listed. ' , & ' -- ARGS optional arguments to pass to the program(s). The same ' , & ' arguments are passed to all program names specified. ' , & ' ' , & help_text_environment , & ' ' , & 'EXAMPLES ' , & ' fpm(1) - run or display project applications: ' , & ' ' , & ' fpm run # run a target when only one exists or list targets ' , & ' fpm run --list # list basename of all targets, running nothing. ' , & ' fpm run \"demo*\" --list # list target basenames starting with \"demo*\".' , & ' fpm run \"psi*\" --runner # list target pathnames starting with \"psi*\".' , & ' fpm run --all # run all targets, no matter how many there are. ' , & ' ' , & ' # run default program built or to be built with the compiler command ' , & ' # \"f90\". If more than one app exists a list displays and target names' , & ' # are required. ' , & ' fpm run --compiler f90 ' , & ' ' , & ' # run example programs instead of the application programs. ' , & ' fpm run --example \"*\" ' , & ' ' , & ' # run a specific program and pass arguments to the command ' , & ' fpm run myprog -- -x 10 -y 20 --title \"my title line\" ' , & ' ' , & ' # run production version of two applications ' , & ' fpm run --target prg1,prg2 --profile release ' , & ' ' , & ' # install executables in directory (assuming install(1) exists) ' , & ' fpm run --runner ''install -b -m 0711 -p -t /usr/local/bin'' ' , & '' ] help_build = [ character ( len = 80 ) :: & 'NAME ' , & ' build(1) - the fpm(1) subcommand to build a project ' , & ' ' , & 'SYNOPSIS ' , & ' fpm build [--profile PROF] [--flag FFLAGS] [--compiler COMPILER_NAME] ' , & ' [--list] [--tests] [--dump [FILENAME]] ' , & ' ' , & ' fpm build --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' The \"fpm build\" command ' , & ' o Fetches any dependencies ' , & ' o Scans your sources ' , & ' o Builds them in the proper order ' , & ' ' , & ' The Fortran source files are assumed by default to be in ' , & ' o src/ for modules and procedure source ' , & ' o app/ main program(s) for applications ' , & ' o test/ main program(s) and support files for project tests ' , & ' o example/ main program(s) for example programs ' , & ' Changed or new files found are rebuilt. The results are placed in ' , & ' the build/ directory. ' , & ' ' , & ' Non-default pathnames and remote dependencies are used if ' , & ' specified in the \"fpm.toml\" file. ' , & ' ' , & 'OPTIONS ' , & help_text_build_common ,& help_text_compiler , & help_text_flag , & ' --list list candidates instead of building or running them ' , & ' --tests build all tests (otherwise only if needed) ' , & ' --show-model show the model and exit (do not build) ' , & ' --dump [FILENAME] save model representation to file. use JSON format ' , & ' if file name is *.json; use TOML format otherwise ' , & ' (default file name: model.toml) ' , & ' --help print this help and exit ' , & ' --version print program version information and exit ' , & ' ' , & help_text_environment , & ' ' , & 'EXAMPLES ' , & ' Sample commands: ' , & ' ' , & ' fpm build # build with debug options ' , & ' fpm build --profile release # build with high optimization ' , & '' ] help_help = [ character ( len = 80 ) :: & 'NAME ' , & ' help(1) - the fpm(1) subcommand to display help ' , & ' ' , & 'SYNOPSIS ' , & ' fpm help [fpm] [new] [build] [run] [test] [help] [version] [manual] ' , & ' [runner] ' , & ' ' , & 'DESCRIPTION ' , & ' The \"fpm help\" command is an alternative to the --help parameter ' , & ' on the fpm(1) command and its subcommands. ' , & ' ' , & 'OPTIONS ' , & ' NAME(s) A list of topic names to display. All the subcommands ' , & ' have their own page (new, build, run, test, ...). ' , & ' ' , & ' The special name \"manual\" displays all the fpm(1) ' , & ' built-in documentation. ' , & ' ' , & ' The default is to display help for the fpm(1) command ' , & ' itself. ' , & ' ' , & 'EXAMPLES ' , & ' Sample usage: ' , & ' ' , & ' fpm help # general fpm(1) command help ' , & ' fpm help version # show program version ' , & ' fpm help new # display help for \"new\" subcommand ' , & ' fpm help manual # All fpm(1) built-in documentation ' , & ' ' , & '' ] help_new = [ character ( len = 80 ) :: & 'NAME ' , & ' new(1) - the fpm(1) subcommand to initialize a new project ' , & ' ' , & 'SYNOPSIS ' , & ' fpm new NAME [[--lib|--src] [--app] [--test] [--example]]| ' , & ' [--full|--bare][--backfill] ' , & ' fpm new --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' \"fpm new\" creates and populates a new programming project directory. ' , & ' ' , & ' It ' , & ' o creates a directory with the specified name ' , & ' o runs the command \"git init\" in that directory ' , & ' o populates the directory with the default project directories ' , & ' o adds sample Fortran source files ' , & ' ' , & ' The default file structure (that will be automatically scanned) is ' , & ' ' , & ' NAME/ ' , & ' fpm.toml ' , & ' src/ ' , & ' NAME.f90 ' , & ' app/ ' , & ' main.f90 ' , & ' test/ ' , & ' check.f90 ' , & ' example/ ' , & ' demo.f90 ' , & ' ' , & ' Using this file structure is highly encouraged, particularly for ' , & ' small packages primarily intended to be used as dependencies. ' , & ' ' , & ' If you find this restrictive and need to customize the package ' , & ' structure you will find using the --full switch creates a ' , & ' heavily annotated manifest file with references to documentation ' , & ' to aid in constructing complex package structures. ' , & ' ' , & ' Remember to update the information in the sample \"fpm.toml\" ' , & ' file with your name and e-mail address. ' , & ' ' , & 'OPTIONS ' , & ' NAME the name of the project directory to create. The name ' , & ' must be made of up to 63 ASCII letters, digits, underscores, ' , & ' or hyphens, and start with a letter. ' , & ' ' , & ' The default is to create the src/, app/, and test/ directories. ' , & ' If any of the following options are specified then only the ' , & ' selected subdirectories are generated: ' , & ' ' , & ' --lib,--src create directory src/ and a placeholder module ' , & ' named \"NAME.f90\" for use with subcommand \"build\". ' , & ' --app create directory app/ and a placeholder main ' , & ' program for use with subcommand \"run\". ' , & ' --test create directory test/ and a placeholder program ' , & ' for use with the subcommand \"test\". Note that sans ' , & ' \"--lib\" it really does not have anything to test. ' , & ' --example create directory example/ and a placeholder program ' , & ' for use with the subcommand \"run --example\". ' , & ' It is only created by default if \"--full is\" specified. ' , & ' ' , & ' So the default is equivalent to ' ,& ' ' , & ' fpm NAME --lib --app --test ' , & ' ' , & ' --backfill By default the directory must not exist. If this ' , & ' option is present the directory may pre-exist and ' , & ' only subdirectories and files that do not ' , & ' already exist will be created. For example, if you ' , & ' previously entered \"fpm new myname --lib\" entering ' , & ' \"fpm new myname -full --backfill\" will create any missing' , & ' app/, example/, and test/ directories and programs. ' , & ' ' , & ' --full By default a minimal manifest file (\"fpm.toml\") is ' , & ' created that depends on auto-discovery. With this ' , & ' option a much more extensive manifest sample is written ' , & ' and the example/ directory is created and populated. ' , & ' It is designed to facilitate creating projects that ' , & ' depend extensively on non-default build options. ' , & ' ' , & ' --bare A minimal manifest file (\"fpm.toml\") is created and ' , & ' \"README.md\" file is created but no directories or ' , & ' sample Fortran are generated. ' , & ' ' , & ' --help print this help and exit ' , & ' --version print program version information and exit ' , & ' ' , & 'EXAMPLES ' , & ' Sample use ' , & ' ' , & ' fpm new myproject # create new project directory and seed it ' , & ' cd myproject # Enter the new directory ' , & ' # and run commands such as ' , & ' fpm build ' , & ' fpm run # run lone example application program ' , & ' fpm test # run example test program(s) ' , & ' fpm run --example # run lone example program ' , & ' ' , & ' fpm new A --full # create example/ and an annotated fpm.toml as well' , & ' fpm new A --bare # create no directories ' , & ' create any missing files in current directory ' , & ' fpm new --full --backfill ' , & '' ] help_test = [ character ( len = 80 ) :: & 'NAME ' , & ' test(1) - the fpm(1) subcommand to run project tests ' , & ' ' , & 'SYNOPSIS ' , & ' fpm test [[--target] NAME(s)] [--profile PROF] [--flag FFLAGS]' , & ' [--compiler COMPILER_NAME ] [--runner \"CMD\"] [--list][-- ARGS]' , & ' ' , & ' fpm test --help|--version ' , & ' ' , & 'DESCRIPTION ' , & ' Run applications you have built to test your project. ' , & ' ' , & 'OPTIONS ' , & ' --target NAME(s) optional list of specific test names to execute. ' , & ' The default is to run all the tests in test/ ' , & ' or the tests listed in the \"fpm.toml\" file. ' , & ' ' , & ' Basic \"globbing\" is supported where \"?\" represents ' , & ' any single character and \"*\" represents any string. ' , & ' Note The glob string normally needs quoted to ' , & ' protect the special characters from shell expansion.' , & help_text_build_common ,& help_text_compiler , & help_text_flag , & ' --runner CMD A command to prefix the program execution paths with. ' , & ' see \"fpm help runner\" for further details. ' , & ' --list list candidate basenames instead of running them. Note they' , & ' --list will still be built if not currently up to date. ' , & ' -- ARGS optional arguments to pass to the test program(s). ' , & ' The same arguments are passed to all test names ' , & ' specified. ' , & ' ' , & help_text_environment , & ' ' , & 'EXAMPLES ' , & 'run tests ' , & ' ' , & ' # run default tests in /test or as specified in \"fpm.toml\" ' , & ' fpm test ' , & ' ' , & ' # run using compiler command \"f90\" ' , & ' fpm test --compiler f90 ' , & ' ' , & ' # run a specific test and pass arguments to the command ' , & ' fpm test mytest -- -x 10 -y 20 --title \"my title line\" ' , & ' ' , & ' fpm test tst1 tst2 --profile PROF # run production version of two tests' , & '' ] help_update = [ character ( len = 80 ) :: & 'NAME' , & ' update(1) - manage project dependencies' , & '' , & 'SYNOPSIS' , & ' fpm update [--fetch-only] [--clean] [--verbose] [--dump [FILENAME]] [NAME(s)]' , & '' , & 'DESCRIPTION' , & ' Manage and update project dependencies. If no dependency names are' , & ' provided all the dependencies are updated automatically.' , & '' , & 'OPTIONS' , & ' --fetch-only Only fetch dependencies, do not update existing projects' , & ' --clean Do not use previous dependency cache' , & ' --verbose Show additional printout' , & ' --dump [FILENAME] Dump updated dependency tree to file. use JSON format ' , & ' if file name is *.json; use TOML format otherwise ' , & ' (default file name: fpm_dependencies.toml) ' , & '' , & 'SEE ALSO' , & ' The fpm(1) home page at https://github.com/fortran-lang/fpm' , & '' ] help_install = [ character ( len = 80 ) :: & 'NAME' , & ' install(1) - install fpm projects' , & '' , & 'SYNOPSIS' , & ' fpm install [--profile PROF] [--flag FFLAGS] [--list] [--no-rebuild]' , & ' [--prefix DIR] [--bindir DIR] [--libdir DIR] [--includedir DIR]' , & ' [--verbose]' , & '' , & 'DESCRIPTION' , & ' Subcommand to install fpm projects. Running install will export the' , & ' current project to the selected prefix, this will by default install all' , & ' executables (tests and examples are excluded) which are part of the projects.' , & ' Libraries and module files are only installed for projects requiring the' , & ' installation of those components in the package manifest.' , & '' , & 'OPTIONS' , & ' --list list all installable targets for this project,' , & ' but do not install any of them' , & help_text_build_common ,& help_text_flag , & ' --no-rebuild do not rebuild project before installation' , & ' --prefix DIR path to installation directory (requires write access),' , & ' the default prefix on Unix systems is $HOME/.local' , & ' and %APPDATA%\\local on Windows' , & ' --bindir DIR subdirectory to place executables in (default: bin)' , & ' --libdir DIR subdirectory to place libraries and archives in' , & ' (default: lib)' , & ' --includedir DIR subdirectory to place headers and module files in' , & ' (default: include)' , & ' --verbose print more information' , & '' , & help_text_environment , & '' , & 'EXAMPLES' , & ' 1. Install release version of project:' , & '' , & ' fpm install --profile release' , & '' , & ' 2. Install the project without rebuilding the executables:' , & '' , & ' fpm install --no-rebuild' , & '' , & ' 3. Install executables to a custom prefix into the exe directory:' , & '' , & ' fpm install --prefix $PWD --bindir exe' , & '' ] help_clean = [ character ( len = 80 ) :: & 'NAME' , & ' clean(1) - delete the build' , & '' , & 'SYNOPSIS' , & ' fpm clean' , & '' , & 'DESCRIPTION' , & ' Prompts the user to confirm deletion of the build. If affirmative,' , & ' directories in the build/ directory are deleted, except dependencies.' , & ' Use the --registry-cache option to delete the registry cache.' , & '' , & 'OPTIONS' , & ' --skip Delete the build without prompting but skip dependencies.' , & ' --all Delete the build without prompting including dependencies.' , & ' --registry-cache Delete registry cache.' , & '' ] help_publish = [ character ( len = 80 ) :: & 'NAME' , & ' publish(1) - publish package to the registry' , & '' , & 'SYNOPSIS' , & ' fpm publish [--token TOKEN] [--show-package-version] [--show-upload-data]' , & ' [--dry-run] [--verbose] ' , & '' , & ' fpm publish --help|--version' , & '' , & 'DESCRIPTION' , & ' Follow the steps to create a tarball and upload a package to the registry:' , & '' , & ' 1. Register on the website (https://registry-phi.vercel.app/).' , & ' 2. Create a namespace. Uploaded packages must be assigned to a unique' , & ' namespace to avoid conflicts among packages with similar names. A' , & ' namespace can accommodate multiple packages.' , & ' 3. Create a token for that namespace. A token is linked to your username' , & ' and is used to authenticate you during the upload process. Do not share' , & ' the token with others.' , & ' 4. Run fpm publish --token TOKEN to upload the package to the registry.' , & ' But be aware that the upload is permanent. An uploaded package cannot be' , & ' deleted.' , & '' , & ' See documentation for more information regarding package upload and usage:' , & '' , & ' Package upload:' , & ' https://fpm.fortran-lang.org/spec/publish.html' , & '' , & ' Package usage:' , & ' https://fpm.fortran-lang.org/spec/manifest.html#dependencies-from-a-registry' , & '' , & 'OPTIONS' , & ' --show-package-version show package version without publishing' , & ' --show-upload-data show upload data without publishing' , & ' --dry-run perform dry run without publishing' , & ' --help print this help and exit' , & ' --version print program version information and exit' , & ' --verbose print more information' , & '' , & 'EXAMPLES' , & '' , & ' fpm publish --show-package-version # show package version without publishing' , & ' fpm publish --show-upload-data # show upload data without publishing' , & ' fpm publish --token TOKEN --dry-run # perform dry run without publishing' , & ' fpm publish --token TOKEN # upload package to the registry' , & '' ] end subroutine set_help subroutine get_char_arg ( var , arg ) character ( len = :), allocatable , intent ( out ) :: var character ( len =* ), intent ( in ) :: arg var = sget ( arg ) if ( len_trim ( var ) == 0 ) deallocate ( var ) end subroutine get_char_arg !> Get an environment variable for fpm, this routine ensures that every variable !> used by fpm is prefixed with FPM_. function get_fpm_env ( env , default ) result ( val ) character ( len =* ), intent ( in ) :: env character ( len =* ), intent ( in ) :: default character ( len = :), allocatable :: val character ( len =* ), parameter :: fpm_prefix = \"FPM_\" val = get_env ( fpm_prefix // env , default ) end function get_fpm_env !> Build a full runner command (executable + command-line arguments) function runner_command ( cmd ) result ( run_cmd ) class ( fpm_run_settings ), intent ( in ) :: cmd character ( len = :), allocatable :: run_cmd !> Get executable if ( len_trim ( cmd % runner ) > 0 ) then run_cmd = trim ( cmd % runner ) else run_cmd = '' end if !> Append command-line arguments if ( len_trim ( cmd % runner_args ) > 0 ) run_cmd = run_cmd // ' ' // trim ( cmd % runner_args ) end function runner_command !> Check name in list ID. return 0 if not found integer function name_ID ( cmd , name ) class ( fpm_run_settings ), intent ( in ) :: cmd character ( * ), intent ( in ) :: name integer :: j !> Default: not found name_ID = 0 if (. not . allocated ( cmd % name )) return do j = 1 , size ( cmd % name ) if ( glob ( trim ( name ), trim ( cmd % name ( j )))) then name_ID = j return end if end do end function name_ID end module fpm_command_line","tags":"","loc":"sourcefile/fpm_command_line.f90.html"},{"title":"update.f90 – Fortran-lang/fpm","text":"Source Code module fpm_cmd_update use fpm_command_line , only : fpm_update_settings use fpm_dependency , only : dependency_tree_t , new_dependency_tree use fpm_error , only : error_t , fpm_stop use fpm_filesystem , only : exists , mkdir , join_path , delete_file , filewrite use fpm_manifest , only : package_config_t , get_package_data use fpm_toml , only : name_is_json implicit none private public :: cmd_update contains !> Entry point for the update subcommand subroutine cmd_update ( settings ) !> Representation of the command line arguments type ( fpm_update_settings ), intent ( in ) :: settings type ( package_config_t ) :: package type ( dependency_tree_t ) :: deps type ( error_t ), allocatable :: error integer :: ii character ( len = :), allocatable :: cache call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) if (. not . exists ( \"build\" )) then call mkdir ( \"build\" ) call filewrite ( join_path ( \"build\" , \".gitignore\" ),[ \"*\" ]) end if cache = join_path ( \"build\" , \"cache.toml\" ) if ( settings % clean ) call delete_file ( cache ) call new_dependency_tree ( deps , cache = cache , & verbosity = merge ( 2 , 1 , settings % verbose )) call deps % add ( package , error ) call handle_error ( error ) ! Force-update all dependencies if `--clean` if ( settings % clean ) then do ii = 1 , deps % ndep deps % dep ( ii )% update = . true . end do end if if ( settings % fetch_only ) return if ( size ( settings % name ) == 0 ) then call deps % update ( error ) call handle_error ( error ) else do ii = 1 , size ( settings % name ) call deps % update ( trim ( settings % name ( ii )), error ) call handle_error ( error ) end do end if if ( len_trim ( settings % dump ) > 0 ) then call deps % dump ( trim ( settings % dump ), error , json = name_is_json ( trim ( settings % dump ))) call handle_error ( error ) end if end subroutine cmd_update !> Error handling for this command subroutine handle_error ( error ) !> Potential error type ( error_t ), intent ( in ), optional :: error if ( present ( error )) then call fpm_stop ( 1 , '*cmd_update* error: ' // error % message ) end if end subroutine handle_error end module fpm_cmd_update","tags":"","loc":"sourcefile/update.f90.html"},{"title":"export.f90 – Fortran-lang/fpm","text":"Source Code module fpm_cmd_export use fpm_command_line , only : fpm_export_settings use fpm_dependency , only : dependency_tree_t , new_dependency_tree use fpm_error , only : error_t , fpm_stop use fpm_filesystem , only : join_path use fpm_manifest , only : package_config_t , get_package_data use fpm_toml , only : name_is_json use fpm_model , only : fpm_model_t use fpm , only : build_model implicit none private public :: cmd_export contains !> Entry point for the export subcommand subroutine cmd_export ( settings ) !> Representation of the command line arguments type ( fpm_export_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( dependency_tree_t ) :: deps type ( fpm_model_t ) :: model type ( error_t ), allocatable :: error integer :: ii character ( len = :), allocatable :: filename if ( len_trim ( settings % dump_manifest ) <= 0 . and . & len_trim ( settings % dump_model ) <= 0 . and . & len_trim ( settings % dump_dependencies ) <= 0 ) then call fpm_stop ( 0 , '*cmd_export* exiting: no manifest/model/dependencies keyword provided' ) end if !> Read in manifest call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) call handle_error ( error ) !> Export manifest if ( len_trim ( settings % dump_manifest ) > 0 ) then filename = trim ( settings % dump_manifest ) call package % dump ( filename , error , json = name_is_json ( filename )) end if !> Export dependency tree if ( len_trim ( settings % dump_dependencies ) > 0 ) then !> Generate dependency tree filename = join_path ( \"build\" , \"cache.toml\" ) call new_dependency_tree ( deps , cache = filename , verbosity = merge ( 2 , 1 , settings % verbose )) call deps % add ( package , error ) call handle_error ( error ) !> Export dependency tree filename = settings % dump_dependencies call deps % dump ( filename , error , json = name_is_json ( filename )) call handle_error ( error ) end if !> Export full model if ( len_trim ( settings % dump_model ) > 0 ) then call build_model ( model , settings % fpm_build_settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_export* Model error: ' // error % message ) end if filename = settings % dump_model call model % dump ( filename , error , json = name_is_json ( filename )) call handle_error ( error ) end if end subroutine cmd_export !> Error handling for this command subroutine handle_error ( error ) !> Potential error type ( error_t ), intent ( in ), optional :: error if ( present ( error )) then call fpm_stop ( 1 , '*cmd_export* error: ' // error % message ) end if end subroutine handle_error end module fpm_cmd_export","tags":"","loc":"sourcefile/export.f90.html"},{"title":"downloader.f90 – Fortran-lang/fpm","text":"Source Code module fpm_downloader use fpm_error , only : error_t , fatal_error use fpm_filesystem , only : which , run use fpm_versioning , only : version_t use jonquil , only : json_object , json_value , json_error , json_load , cast_to_object use fpm_strings , only : string_t implicit none private public :: downloader_t !> This type could be entirely avoided but it is quite practical because it can be mocked for testing. type downloader_t contains procedure , nopass :: get_pkg_data , get_file , upload_form , unpack end type contains !> Perform an http get request, save output to file, and parse json. subroutine get_pkg_data ( url , version , tmp_pkg_file , json , error ) character ( * ), intent ( in ) :: url type ( version_t ), allocatable , intent ( in ) :: version character ( * ), intent ( in ) :: tmp_pkg_file type ( json_object ), intent ( out ) :: json type ( error_t ), allocatable , intent ( out ) :: error class ( json_value ), allocatable :: j_value type ( json_object ), pointer :: ptr type ( json_error ), allocatable :: j_error if ( allocated ( version )) then ! Request specific version. call get_file ( url // '/' // version % s (), tmp_pkg_file , error ) else ! Request latest version. call get_file ( url , tmp_pkg_file , error ) end if if ( allocated ( error )) return call json_load ( j_value , tmp_pkg_file , error = j_error ) if ( allocated ( j_error )) then allocate ( error ); call move_alloc ( j_error % message , error % message ); call json % destroy (); return end if ptr => cast_to_object ( j_value ) if (. not . associated ( ptr )) then call fatal_error ( error , \"Error parsing JSON from '\" // url // \"'.\" ); return end if json = ptr end !> Download a file from a url using either curl or wget. subroutine get_file ( url , tmp_pkg_file , error ) character ( * ), intent ( in ) :: url character ( * ), intent ( in ) :: tmp_pkg_file type ( error_t ), allocatable , intent ( out ) :: error integer :: stat if ( which ( 'curl' ) /= '' ) then print * , \"Downloading '\" // url // \"' -> '\" // tmp_pkg_file // \"'\" call execute_command_line ( 'curl ' // url // ' -s -o ' // tmp_pkg_file , exitstat = stat ) else if ( which ( 'wget' ) /= '' ) then print * , \"Downloading '\" // url // \"' -> '\" // tmp_pkg_file // \"'\" call execute_command_line ( 'wget ' // url // ' -q -O ' // tmp_pkg_file , exitstat = stat ) else call fatal_error ( error , \"Neither 'curl' nor 'wget' installed.\" ); return end if if ( stat /= 0 ) then call fatal_error ( error , \"Error downloading package from '\" // url // \"'.\" ); return end if end !> Perform an http post request with form data. subroutine upload_form ( endpoint , form_data , verbose , error ) !> Endpoint to upload to. character ( len =* ), intent ( in ) :: endpoint !> Form data to upload. type ( string_t ), intent ( in ) :: form_data (:) !> Print additional information if true. logical , intent ( in ) :: verbose !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , i character ( len = :), allocatable :: form_data_str form_data_str = '' do i = 1 , size ( form_data ) form_data_str = form_data_str // \"-F '\" // form_data ( i )% s // \"' \" end do if ( which ( 'curl' ) /= '' ) then print * , 'Uploading package ...' call run ( 'curl -X POST -H \"Content-Type: multipart/form-data\" ' // & & form_data_str // endpoint , exitstat = stat , echo = verbose ) else call fatal_error ( error , \"'curl' not installed.\" ); return end if if ( stat /= 0 ) then call fatal_error ( error , \"Error uploading package to registry.\" ); return end if end !> Unpack a tarball to a destination. subroutine unpack ( tmp_pkg_file , destination , error ) !> Path to tarball. character ( * ), intent ( in ) :: tmp_pkg_file !> Destination to unpack to. character ( * ), intent ( in ) :: destination !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error integer :: stat if ( which ( 'tar' ) == '' ) then call fatal_error ( error , \"'tar' not installed.\" ); return end if print * , \"Unpacking '\" // tmp_pkg_file // \"' to '\" // destination // \"' ...\" call execute_command_line ( 'tar -zxf ' // tmp_pkg_file // ' -C ' // destination , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error unpacking '\" // tmp_pkg_file // \"'.\" ); return end if end end","tags":"","loc":"sourcefile/downloader.f90.html"},{"title":"dependency.f90 – Fortran-lang/fpm","text":"Source Code !> # Dependency management !> !> ## Fetching dependencies and creating a dependency tree !> !> Dependencies on the top-level can be specified from: !> !> - `package%dependencies` !> - `package%dev_dependencies` !> - `package%executable(:)%dependencies` !> - `package%test(:)%dependencies` !> !> Each dependency is fetched in some way and provides a path to its package !> manifest. !> The `package%dependencies` of the dependencies are resolved recursively. !> !> To initialize the dependency tree all dependencies are recursively fetched !> and stored in a flat data structure to avoid retrieving a package twice. !> The data structure used to store this information should describe the current !> status of the dependency tree. Important information are: !> !> - name of the package !> - version of the package !> - path to the package root !> !> Additionally, for version controlled dependencies the following should be !> stored along with the package: !> !> - the upstream url !> - the current checked out revision !> !> Fetching a remote (version controlled) dependency turns it for our purpose !> into a local path dependency which is handled by the same means. !> !> ## Updating dependencies !> !> For a given dependency tree all top-level dependencies can be updated. !> We have two cases to consider, a remote dependency and a local dependency, !> again, remote dependencies turn into local dependencies by fetching. !> Therefore we will update remote dependencies by simply refetching them. !> !> For remote dependencies we have to refetch if the revision in the manifest !> changes or the upstream HEAD has changed (for branches _and_ tags). !> !> @Note For our purpose a tag is just a fancy branch name. Tags can be delete and !> modified afterwards, therefore they do not differ too much from branches !> from our perspective. !> !> For the latter case we only know if we actually fetch from the upstream URL. !> !> In case of local (and fetched remote) dependencies we have to read the package !> manifest and compare its dependencies against our dependency tree, any change !> requires updating the respective dependencies as well. !> !> ## Handling dependency compatibilties !> !> Currenly ignored. First come, first serve. module fpm_dependency use , intrinsic :: iso_fortran_env , only : output_unit use fpm_environment , only : get_os_type , OS_WINDOWS , os_is_unix use fpm_error , only : error_t , fatal_error use fpm_filesystem , only : exists , join_path , mkdir , canon_path , windows_path , list_files , is_dir , basename , & os_delete_dir , get_temp_filename use fpm_git , only : git_target_revision , git_target_default , git_revision , serializable_t use fpm_manifest , only : package_config_t , dependency_config_t , get_package_data use fpm_manifest_dependency , only : manifest_has_changed , dependency_destroy use fpm_manifest_preprocess , only : operator ( == ) use fpm_strings , only : string_t , operator (. in .) use fpm_toml , only : toml_table , toml_key , toml_error , toml_serialize , & get_value , set_value , add_table , toml_load , toml_stat , set_string use fpm_versioning , only : version_t , new_version use fpm_settings , only : fpm_global_settings , get_global_settings , official_registry_base_url use fpm_downloader , only : downloader_t use jonquil , only : json_object use fpm_strings , only : str implicit none private public :: dependency_tree_t , new_dependency_tree , dependency_node_t , new_dependency_node , resize , & & check_and_read_pkg_data , destroy_dependency_node !> Overloaded reallocation interface interface resize module procedure :: resize_dependency_node end interface resize !> Dependency node in the projects dependency tree type , extends ( dependency_config_t ) :: dependency_node_t !> Actual version of this dependency type ( version_t ), allocatable :: version !> Installation prefix of this dependencies character ( len = :), allocatable :: proj_dir !> Checked out revision of the version control system character ( len = :), allocatable :: revision !> Dependency is handled logical :: done = . false . !> Dependency should be updated logical :: update = . false . !> Dependency was loaded from a cache logical :: cached = . false . contains !> Update dependency from project manifest. procedure :: register !> Get dependency from the registry. procedure :: get_from_registry procedure , private :: get_from_local_registry !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => dependency_node_is_same procedure :: dump_to_toml => node_dump_to_toml procedure :: load_from_toml => node_load_from_toml end type dependency_node_t !> Respresentation of a projects dependencies !> !> The dependencies are stored in a simple array for now, this can be replaced !> with a binary-search tree or a hash table in the future. type , extends ( serializable_t ) :: dependency_tree_t !> Unit for IO integer :: unit = output_unit !> Verbosity of printout integer :: verbosity = 1 !> Installation prefix for dependencies character ( len = :), allocatable :: dep_dir !> Number of currently registered dependencies integer :: ndep = 0 !> Flattend list of all dependencies type ( dependency_node_t ), allocatable :: dep (:) !> Cache file character ( len = :), allocatable :: cache contains !> Overload procedure to add new dependencies to the tree generic :: add => add_project , add_project_dependencies , add_dependencies , & add_dependency , add_dependency_node !> Main entry point to add a project procedure , private :: add_project !> Add a project and its dependencies to the dependency tree procedure , private :: add_project_dependencies !> Add a list of dependencies to the dependency tree procedure , private :: add_dependencies !> Add a single dependency to the dependency tree procedure , private :: add_dependency !> Add a single dependency node to the dependency tree procedure , private :: add_dependency_node !> Resolve dependencies generic :: resolve => resolve_dependencies , resolve_dependency !> Resolve dependencies procedure , private :: resolve_dependencies !> Resolve dependency procedure , private :: resolve_dependency !> True if entity can be found generic :: has => has_dependency !> True if dependency is part of the tree procedure , private :: has_dependency !> Find a dependency in the tree generic :: find => find_name !> Find a dependency by its name procedure , private :: find_name !> Depedendncy resolution finished procedure :: finished !> Reading of dependency tree generic :: load_cache => load_cache_from_file , load_cache_from_unit , load_cache_from_toml !> Read dependency tree from file procedure , private :: load_cache_from_file !> Read dependency tree from formatted unit procedure , private :: load_cache_from_unit !> Read dependency tree from TOML data structure procedure , private :: load_cache_from_toml !> Writing of dependency tree generic :: dump_cache => dump_cache_to_file , dump_cache_to_unit , dump_cache_to_toml !> Write dependency tree to file procedure , private :: dump_cache_to_file !> Write dependency tree to formatted unit procedure , private :: dump_cache_to_unit !> Write dependency tree to TOML data structure procedure , private :: dump_cache_to_toml !> Update dependency tree generic :: update => update_dependency , update_tree !> Update a list of dependencies procedure , private :: update_dependency !> Update all dependencies in the tree procedure , private :: update_tree !> Serialization interface procedure :: serializable_is_same => dependency_tree_is_same procedure :: dump_to_toml => tree_dump_to_toml procedure :: load_from_toml => tree_load_from_toml end type dependency_tree_t !> Common output format for writing to the command line character ( len =* ), parameter :: out_fmt = '(\"#\", *(1x, g0))' contains !> Create a new dependency tree subroutine new_dependency_tree ( self , verbosity , cache ) !> Instance of the dependency tree type ( dependency_tree_t ), intent ( out ) :: self !> Verbosity of printout integer , intent ( in ), optional :: verbosity !> Name of the cache file character ( len =* ), intent ( in ), optional :: cache call resize ( self % dep ) self % dep_dir = join_path ( \"build\" , \"dependencies\" ) if ( present ( verbosity )) self % verbosity = verbosity if ( present ( cache )) self % cache = cache end subroutine new_dependency_tree !> Create a new dependency node from a configuration subroutine new_dependency_node ( self , dependency , version , proj_dir , update ) !> Instance of the dependency node type ( dependency_node_t ), intent ( out ) :: self !> Dependency configuration data type ( dependency_config_t ), intent ( in ) :: dependency !> Version of the dependency type ( version_t ), intent ( in ), optional :: version !> Installation prefix of the dependency character ( len =* ), intent ( in ), optional :: proj_dir !> Dependency should be updated logical , intent ( in ), optional :: update self % dependency_config_t = dependency if ( present ( version )) then self % version = version end if if ( present ( proj_dir )) then self % proj_dir = proj_dir end if if ( present ( update )) then self % update = update end if end subroutine new_dependency_node !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the dependency configuration class ( dependency_node_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if !> Call base object info call self % dependency_config_t % info ( unit , pr ) if ( allocated ( self % version )) then write ( unit , fmt ) \"- version\" , self % version % s () end if if ( allocated ( self % proj_dir )) then write ( unit , fmt ) \"- dir\" , self % proj_dir end if if ( allocated ( self % revision )) then write ( unit , fmt ) \"- revision\" , self % revision end if write ( unit , fmt ) \"- done\" , merge ( 'YES' , 'NO ' , self % done ) write ( unit , fmt ) \"- update\" , merge ( 'YES' , 'NO ' , self % update ) end subroutine info !> Add project dependencies, each depth level after each other. !> !> We implement this algorithm in an interative rather than a recursive fashion !> as a choice of design. subroutine add_project ( self , package , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Project configuration to add type ( package_config_t ), intent ( in ) :: package !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( dependency_config_t ) :: dependency type ( dependency_tree_t ) :: cached character ( len =* ), parameter :: root = '.' integer :: id if (. not . exists ( self % dep_dir )) then call mkdir ( self % dep_dir ) end if ! Create this project as the first dependency node (depth 0) dependency % name = package % name dependency % path = root call self % add ( dependency , error ) if ( allocated ( error )) return ! Resolve the root project call self % resolve ( root , error ) if ( allocated ( error )) return ! Add the root project dependencies (depth 1) call self % add ( package , root , . true ., error ) if ( allocated ( error )) return ! After resolving all dependencies, check if we have cached ones to avoid updates if ( allocated ( self % cache )) then call new_dependency_tree ( cached , verbosity = self % verbosity , cache = self % cache ) call cached % load_cache ( self % cache , error ) if ( allocated ( error )) return ! Skip root node do id = 2 , cached % ndep cached % dep ( id )% cached = . true . call self % add ( cached % dep ( id ), error ) if ( allocated ( error )) return end do end if ! Now decent into the dependency tree, level for level do while (. not . self % finished ()) call self % resolve ( root , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return if ( allocated ( self % cache )) then call self % dump_cache ( self % cache , error ) if ( allocated ( error )) return end if end subroutine add_project !> Add a project and its dependencies to the dependency tree recursive subroutine add_project_dependencies ( self , package , root , main , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Project configuration to add type ( package_config_t ), intent ( in ) :: package !> Current project root directory character ( len =* ), intent ( in ) :: root !> Is the main project logical , intent ( in ) :: main !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ii if ( allocated ( package % dependency )) then call self % add ( package % dependency , error ) if ( allocated ( error )) return end if if ( main ) then if ( allocated ( package % dev_dependency )) then call self % add ( package % dev_dependency , error ) if ( allocated ( error )) return end if if ( allocated ( package % executable )) then do ii = 1 , size ( package % executable ) if ( allocated ( package % executable ( ii )% dependency )) then call self % add ( package % executable ( ii )% dependency , error ) if ( allocated ( error )) exit end if end do if ( allocated ( error )) return end if if ( allocated ( package % example )) then do ii = 1 , size ( package % example ) if ( allocated ( package % example ( ii )% dependency )) then call self % add ( package % example ( ii )% dependency , error ) if ( allocated ( error )) exit end if end do if ( allocated ( error )) return end if if ( allocated ( package % test )) then do ii = 1 , size ( package % test ) if ( allocated ( package % test ( ii )% dependency )) then call self % add ( package % test ( ii )% dependency , error ) if ( allocated ( error )) exit end if end do if ( allocated ( error )) return end if end if !> Ensure allocation fits call resize ( self % dep , self % ndep ) end subroutine add_project_dependencies !> Add a list of dependencies to the dependency tree subroutine add_dependencies ( self , dependency , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Dependency configuration to add type ( dependency_config_t ), intent ( in ) :: dependency (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ii , ndep ndep = size ( self % dep ) if ( ndep < size ( dependency ) + self % ndep ) then call resize ( self % dep , ndep + ndep / 2 + size ( dependency )) end if do ii = 1 , size ( dependency ) call self % add ( dependency ( ii ), error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return !> Ensure allocation fits ndep call resize ( self % dep , self % ndep ) end subroutine add_dependencies !> Add a single dependency node to the dependency tree !> Dependency nodes contain additional information (version, git, revision) subroutine add_dependency_node ( self , dependency , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Dependency configuration to add type ( dependency_node_t ), intent ( in ) :: dependency !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: id if ( self % has_dependency ( dependency )) then ! A dependency with this same name is already in the dependency tree. ! Check if it needs to be updated id = self % find ( dependency % name ) ! If this dependency was in the cache, and we're now requesting a different version ! in the manifest, ensure it is marked for update. Otherwise, if we're just querying ! the same dependency from a lower branch of the dependency tree, the existing one from ! the manifest has priority if ( dependency % cached ) then if ( dependency_has_changed ( dependency , self % dep ( id ), self % verbosity , self % unit )) then if ( self % verbosity > 0 ) write ( self % unit , out_fmt ) \"Dependency change detected:\" , dependency % name self % dep ( id )% update = . true . else ! Store the cached one self % dep ( id ) = dependency self % dep ( id )% update = . false . end if end if else !> Safety: reallocate if necessary if ( size ( self % dep ) == self % ndep ) call resize ( self % dep , self % ndep + 1 ) ! New dependency: add from scratch self % ndep = self % ndep + 1 self % dep ( self % ndep ) = dependency self % dep ( self % ndep )% update = . false . end if end subroutine add_dependency_node !> Add a single dependency to the dependency tree subroutine add_dependency ( self , dependency , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Dependency configuration to add type ( dependency_config_t ), intent ( in ) :: dependency !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( dependency_node_t ) :: node call new_dependency_node ( node , dependency ) call add_dependency_node ( self , node , error ) end subroutine add_dependency !> Update dependency tree subroutine update_dependency ( self , name , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Name of the dependency to update character ( len =* ), intent ( in ) :: name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: id character ( len = :), allocatable :: proj_dir , root id = self % find ( name ) root = \".\" if ( id <= 0 ) then call fatal_error ( error , \"Cannot update dependency '\" // name // \"'\" ) return end if associate ( dep => self % dep ( id )) if ( allocated ( dep % git ) . and . dep % update ) then if ( self % verbosity > 0 ) write ( self % unit , out_fmt ) \"Update:\" , dep % name proj_dir = join_path ( self % dep_dir , dep % name ) call dep % git % checkout ( proj_dir , error ) if ( allocated ( error )) return ! Unset dependency and remove updatable attribute dep % done = . false . dep % update = . false . ! Now decent into the dependency tree, level for level do while (. not . self % finished ()) call self % resolve ( root , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return end if end associate end subroutine update_dependency !> Update whole dependency tree subroutine update_tree ( self , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: i ! Update dependencies where needed do i = 1 , self % ndep call self % update ( self % dep ( i )% name , error ) if ( allocated ( error )) return end do end subroutine update_tree !> Resolve all dependencies in the tree subroutine resolve_dependencies ( self , root , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Current installation prefix character ( len =* ), intent ( in ) :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( fpm_global_settings ) :: global_settings integer :: ii call get_global_settings ( global_settings , error ) if ( allocated ( error )) return do ii = 1 , self % ndep call self % resolve ( self % dep ( ii ), global_settings , root , error ) if ( allocated ( error )) exit end do if ( allocated ( error )) return end subroutine resolve_dependencies !> Resolve a single dependency node subroutine resolve_dependency ( self , dependency , global_settings , root , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Dependency configuration to add type ( dependency_node_t ), intent ( inout ) :: dependency !> Global configuration settings. type ( fpm_global_settings ), intent ( in ) :: global_settings !> Current installation prefix character ( len =* ), intent ( in ) :: root !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( package_config_t ) :: package character ( len = :), allocatable :: manifest , proj_dir , revision logical :: fetch if ( dependency % done ) return fetch = . false . if ( allocated ( dependency % proj_dir )) then proj_dir = dependency % proj_dir else if ( allocated ( dependency % path )) then proj_dir = join_path ( root , dependency % path ) else if ( allocated ( dependency % git )) then proj_dir = join_path ( self % dep_dir , dependency % name ) fetch = . not . exists ( proj_dir ) if ( fetch ) then call dependency % git % checkout ( proj_dir , error ) if ( allocated ( error )) return end if else call dependency % get_from_registry ( proj_dir , global_settings , error ) if ( allocated ( error )) return end if if ( allocated ( dependency % git )) then call git_revision ( proj_dir , revision , error ) if ( allocated ( error )) return end if manifest = join_path ( proj_dir , \"fpm.toml\" ) call get_package_data ( package , manifest , error ) if ( allocated ( error )) return call dependency % register ( package , proj_dir , fetch , revision , error ) if ( allocated ( error )) return if ( self % verbosity > 1 ) then write ( self % unit , out_fmt ) & \"Dep:\" , dependency % name , \"version\" , dependency % version % s (), & \"at\" , dependency % proj_dir end if call self % add ( package , proj_dir , . false ., error ) if ( allocated ( error )) return end subroutine resolve_dependency !> Get a dependency from the registry. Whether the dependency is fetched !> from a local, a custom remote or the official registry is determined !> by the global configuration settings. subroutine get_from_registry ( self , target_dir , global_settings , error , downloader_ ) !> Instance of the dependency configuration. class ( dependency_node_t ), intent ( in ) :: self !> The target directory of the dependency. character (:), allocatable , intent ( out ) :: target_dir !> Global configuration settings. type ( fpm_global_settings ), intent ( in ) :: global_settings !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error !> Downloader instance. class ( downloader_t ), optional , intent ( in ) :: downloader_ character (:), allocatable :: cache_path , target_url , tmp_file type ( version_t ) :: version integer :: stat , unit type ( json_object ) :: json class ( downloader_t ), allocatable :: downloader if ( present ( downloader_ )) then downloader = downloader_ else allocate ( downloader ) end if ! Use local registry if it was specified in the global config file. if ( allocated ( global_settings % registry_settings % path )) then call self % get_from_local_registry ( target_dir , global_settings % registry_settings % path , error ); return end if ! Include namespace and package name in the cache path. cache_path = join_path ( global_settings % registry_settings % cache_path , self % namespace , self % name ) ! Check cache before downloading from the remote registry if a specific version was requested. When no specific ! version was requested, do network request first to check which is the newest version. if ( allocated ( self % requested_version )) then if ( exists ( join_path ( cache_path , self % requested_version % s (), 'fpm.toml' ))) then print * , \"Using cached version of '\" , join_path ( self % namespace , self % name , self % requested_version % s ()), \"'.\" target_dir = join_path ( cache_path , self % requested_version % s ()); return end if end if tmp_file = get_temp_filename () open ( newunit = unit , file = tmp_file , action = 'readwrite' , iostat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error creating temporary file for downloading package '\" // self % name // \"'.\" ); return end if ! Include namespace and package name in the target url and download package data. target_url = global_settings % registry_settings % url // 'packages/' // self % namespace // '/' // self % name call downloader % get_pkg_data ( target_url , self % requested_version , tmp_file , json , error ) close ( unit , status = 'delete' ) if ( allocated ( error )) return ! Verify package data and read relevant information. call check_and_read_pkg_data ( json , self , target_url , version , error ) if ( allocated ( error )) return ! Open new tmp file for downloading the actual package. open ( newunit = unit , file = tmp_file , action = 'readwrite' , iostat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Error creating temporary file for downloading package '\" // self % name // \"'.\" ); return end if ! Include version number in the cache path. If no cached version exists, download it. cache_path = join_path ( cache_path , version % s ()) if (. not . exists ( join_path ( cache_path , 'fpm.toml' ))) then if ( is_dir ( cache_path )) call os_delete_dir ( os_is_unix (), cache_path ) call mkdir ( cache_path ) call downloader % get_file ( target_url , tmp_file , error ) if ( allocated ( error )) then close ( unit , status = 'delete' ); return end if ! Unpack the downloaded package to the final location. call downloader % unpack ( tmp_file , cache_path , error ) close ( unit , status = 'delete' ) if ( allocated ( error )) return end if target_dir = cache_path end subroutine get_from_registry subroutine check_and_read_pkg_data ( json , node , download_url , version , error ) type ( json_object ), intent ( inout ) :: json class ( dependency_node_t ), intent ( in ) :: node character (:), allocatable , intent ( out ) :: download_url type ( version_t ), intent ( out ) :: version type ( error_t ), allocatable , intent ( out ) :: error integer :: code , stat type ( json_object ), pointer :: p , q character (:), allocatable :: version_key , version_str , error_message , namespace , name namespace = \"\" name = \"UNNAMED_NODE\" if ( allocated ( node % namespace )) namespace = node % namespace if ( allocated ( node % name )) name = node % name if (. not . json % has_key ( 'code' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No status code.\" ); return end if call get_value ( json , 'code' , code , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': \" // & & \"Failed to read status code.\" ); return end if if ( code /= 200 ) then if (. not . json % has_key ( 'message' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No error message.\" ); return end if call get_value ( json , 'message' , error_message , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': \" // & & \"Failed to read error message.\" ); return end if call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"'. Status code: '\" // & & str ( code ) // \"'. Error message: '\" // error_message // \"'.\" ); return end if if (. not . json % has_key ( 'data' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No data.\" ); return end if call get_value ( json , 'data' , p , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to read package data for '\" // join_path ( namespace , name ) // \"'.\" ); return end if if ( allocated ( node % requested_version )) then version_key = 'version_data' else version_key = 'latest_version_data' end if if (. not . p % has_key ( version_key )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No version data.\" ); return end if call get_value ( p , version_key , q , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to retrieve version data for '\" // join_path ( namespace , name ) // \"'.\" ); return end if if (. not . q % has_key ( 'download_url' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No download url.\" ); return end if call get_value ( q , 'download_url' , download_url , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to read download url for '\" // join_path ( namespace , name ) // \"'.\" ); return end if download_url = official_registry_base_url // download_url if (. not . q % has_key ( 'version' )) then call fatal_error ( error , \"Failed to download '\" // join_path ( namespace , name ) // \"': No version found.\" ); return end if call get_value ( q , 'version' , version_str , stat = stat ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to read version data for '\" // join_path ( namespace , name ) // \"'.\" ); return end if call new_version ( version , version_str , error ) if ( allocated ( error )) then call fatal_error ( error , \"'\" // version_str // \"' is not a valid version for '\" // & & join_path ( namespace , name ) // \"'.\" ); return end if end subroutine !> Get the dependency from a local registry. subroutine get_from_local_registry ( self , target_dir , registry_path , error ) !> Instance of the dependency configuration. class ( dependency_node_t ), intent ( in ) :: self !> The target directory to download the dependency to. character (:), allocatable , intent ( out ) :: target_dir !> The path to the local registry. character ( * ), intent ( in ) :: registry_path !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error character (:), allocatable :: path_to_name type ( string_t ), allocatable :: files (:) type ( version_t ), allocatable :: versions (:) type ( version_t ) :: version integer :: i path_to_name = join_path ( registry_path , self % namespace , self % name ) if (. not . exists ( path_to_name )) then call fatal_error ( error , \"Dependency resolution of '\" // self % name // & & \"': Directory '\" // path_to_name // \"' doesn't exist.\" ); return end if call list_files ( path_to_name , files ) if ( size ( files ) == 0 ) then call fatal_error ( error , \"No versions of '\" // self % name // \"' found in '\" // path_to_name // \"'.\" ); return end if ! Version requested, find it in the cache. if ( allocated ( self % requested_version )) then do i = 1 , size ( files ) ! Identify directory that matches the version number. if ( files ( i )% s == join_path ( path_to_name , self % requested_version % s ()) . and . is_dir ( files ( i )% s )) then if (. not . exists ( join_path ( files ( i )% s , 'fpm.toml' ))) then call fatal_error ( error , \"'\" // files ( i )% s // \"' is missing an 'fpm.toml' file.\" ); return end if target_dir = files ( i )% s ; return end if end do call fatal_error ( error , \"Version '\" // self % requested_version % s () // \"' not found in '\" // path_to_name // \"'\" ) return end if ! No specific version requested, therefore collect available versions. allocate ( versions ( 0 )) do i = 1 , size ( files ) if ( is_dir ( files ( i )% s )) then call new_version ( version , basename ( files ( i )% s ), error ) if ( allocated ( error )) return versions = [ versions , version ] end if end do if ( size ( versions ) == 0 ) then call fatal_error ( error , \"No versions found in '\" // path_to_name // \"'\" ); return end if ! Find the latest version. version = versions ( 1 ) do i = 1 , size ( versions ) if ( versions ( i ) > version ) version = versions ( i ) end do path_to_name = join_path ( path_to_name , version % s ()) if (. not . exists ( join_path ( path_to_name , 'fpm.toml' ))) then call fatal_error ( error , \"'\" // path_to_name // \"' is missing an 'fpm.toml' file.\" ); return end if target_dir = path_to_name end subroutine get_from_local_registry !> True if dependency is part of the tree pure logical function has_dependency ( self , dependency ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( in ) :: self !> Dependency configuration to check class ( dependency_node_t ), intent ( in ) :: dependency has_dependency = self % find ( dependency % name ) /= 0 end function has_dependency !> Find a dependency in the dependency tree pure function find_name ( self , name ) result ( pos ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( in ) :: self !> Dependency configuration to add character ( len =* ), intent ( in ) :: name !> Index of the dependency integer :: pos integer :: ii pos = 0 do ii = 1 , self % ndep if ( name == self % dep ( ii )% name ) then pos = ii exit end if end do end function find_name !> Check if we are done with the dependency resolution pure function finished ( self ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( in ) :: self !> All dependencies are updated logical :: finished finished = all ( self % dep (: self % ndep )% done ) end function finished !> Update dependency from project manifest subroutine register ( self , package , root , fetch , revision , error ) !> Instance of the dependency node class ( dependency_node_t ), intent ( inout ) :: self !> Package configuration data type ( package_config_t ), intent ( in ) :: package !> Project has been fetched logical , intent ( in ) :: fetch !> Root directory of the project character ( len =* ), intent ( in ) :: root !> Git revision of the project character ( len =* ), intent ( in ), optional :: revision !> Error handling type ( error_t ), allocatable , intent ( out ) :: error logical :: update update = . false . if ( self % name /= package % name ) then call fatal_error ( error , \"Dependency name '\" // package % name // & & \"' found, but expected '\" // self % name // \"' instead\" ) end if self % version = package % version self % proj_dir = root if ( allocated ( self % git ) . and . present ( revision )) then self % revision = revision if (. not . fetch ) then ! Change in revision ID was checked already. Only update if ALL git information is missing update = . not . allocated ( self % git % url ) end if end if if ( update ) self % update = update self % done = . true . end subroutine register !> Read dependency tree from file subroutine load_cache_from_file ( self , file , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> File name character ( len =* ), intent ( in ) :: file !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: unit logical :: exist inquire ( file = file , exist = exist ) if (. not . exist ) return open ( file = file , newunit = unit ) call self % load_cache ( unit , error ) close ( unit ) end subroutine load_cache_from_file !> Read dependency tree from file subroutine load_cache_from_unit ( self , unit , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> File name integer , intent ( in ) :: unit !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_error ), allocatable :: parse_error type ( toml_table ), allocatable :: table call toml_load ( table , unit , error = parse_error ) if ( allocated ( parse_error )) then allocate ( error ) call move_alloc ( parse_error % message , error % message ) return end if call self % load_cache ( table , error ) if ( allocated ( error )) return end subroutine load_cache_from_unit !> Read dependency tree from TOML data structure subroutine load_cache_from_toml ( self , table , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ndep , ii logical :: is_unix character ( len = :), allocatable :: version , url , obj , rev , proj_dir type ( toml_key ), allocatable :: list (:) type ( toml_table ), pointer :: ptr call table % get_keys ( list ) ndep = size ( self % dep ) if ( ndep < size ( list ) + self % ndep ) then call resize ( self % dep , ndep + ndep / 2 + size ( list )) end if is_unix = get_os_type () /= OS_WINDOWS do ii = 1 , size ( list ) call get_value ( table , list ( ii )% key , ptr ) call get_value ( ptr , \"version\" , version ) call get_value ( ptr , \"proj-dir\" , proj_dir ) call get_value ( ptr , \"git\" , url ) call get_value ( ptr , \"obj\" , obj ) call get_value ( ptr , \"rev\" , rev ) if (. not . allocated ( proj_dir )) cycle self % ndep = self % ndep + 1 associate ( dep => self % dep ( self % ndep )) dep % name = list ( ii )% key if ( is_unix ) then dep % proj_dir = proj_dir else dep % proj_dir = windows_path ( proj_dir ) end if dep % done = . false . if ( allocated ( version )) then if (. not . allocated ( dep % version )) allocate ( dep % version ) call new_version ( dep % version , version , error ) if ( allocated ( error )) exit end if if ( allocated ( url )) then if ( allocated ( obj )) then dep % git = git_target_revision ( url , obj ) else dep % git = git_target_default ( url ) end if if ( allocated ( rev )) then dep % revision = rev end if else dep % path = proj_dir end if end associate end do if ( allocated ( error )) return self % ndep = size ( list ) end subroutine load_cache_from_toml !> Write dependency tree to file subroutine dump_cache_to_file ( self , file , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> File name character ( len =* ), intent ( in ) :: file !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: unit open ( file = file , newunit = unit ) call self % dump_cache ( unit , error ) close ( unit ) if ( allocated ( error )) return end subroutine dump_cache_to_file !> Write dependency tree to file subroutine dump_cache_to_unit ( self , unit , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Formatted unit integer , intent ( in ) :: unit !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ) :: table table = toml_table () call self % dump_cache ( table , error ) write ( unit , '(a)' ) toml_serialize ( table ) end subroutine dump_cache_to_unit !> Write dependency tree to TOML datastructure subroutine dump_cache_to_toml ( self , table , error ) !> Instance of the dependency tree class ( dependency_tree_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ii type ( toml_table ), pointer :: ptr character ( len = :), allocatable :: proj_dir do ii = 1 , self % ndep associate ( dep => self % dep ( ii )) call add_table ( table , dep % name , ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , \"Cannot create entry for \" // dep % name ) exit end if if ( allocated ( dep % version )) then call set_value ( ptr , \"version\" , dep % version % s ()) end if proj_dir = canon_path ( dep % proj_dir ) call set_value ( ptr , \"proj-dir\" , proj_dir ) if ( allocated ( dep % git )) then call set_value ( ptr , \"git\" , dep % git % url ) if ( allocated ( dep % git % object )) then call set_value ( ptr , \"obj\" , dep % git % object ) end if if ( allocated ( dep % revision )) then call set_value ( ptr , \"rev\" , dep % revision ) end if end if end associate end do if ( allocated ( error )) return end subroutine dump_cache_to_toml !> Reallocate a list of dependencies pure subroutine resize_dependency_node ( var , n ) !> Instance of the array to be resized type ( dependency_node_t ), allocatable , intent ( inout ) :: var (:) !> Dimension of the final array size integer , intent ( in ), optional :: n type ( dependency_node_t ), allocatable :: tmp (:) integer :: this_size , new_size integer , parameter :: initial_size = 16 if ( allocated ( var )) then this_size = size ( var , 1 ) call move_alloc ( var , tmp ) else this_size = initial_size end if if ( present ( n )) then new_size = n else new_size = this_size + this_size / 2 + 1 end if allocate ( var ( new_size )) if ( allocated ( tmp )) then this_size = min ( size ( tmp , 1 ), size ( var , 1 )) var (: this_size ) = tmp (: this_size ) deallocate ( tmp ) end if end subroutine resize_dependency_node !> Check if a dependency node has changed logical function dependency_has_changed ( cached , manifest , verbosity , iunit ) result ( has_changed ) !> Two instances of the same dependency to be compared type ( dependency_node_t ), intent ( in ) :: cached , manifest !> Log verbosity integer , intent ( in ) :: verbosity , iunit integer :: ip has_changed = . true . !> All the following entities must be equal for the dependency to not have changed if ( manifest_has_changed ( cached = cached , manifest = manifest , verbosity = verbosity , iunit = iunit )) return !> For now, only perform the following checks if both are available. A dependency in cache.toml !> will always have this metadata; a dependency from fpm.toml which has not been fetched yet !> may not have it if ( allocated ( cached % version ) . and . allocated ( manifest % version )) then if ( cached % version /= manifest % version ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"VERSION has changed: \" // cached % version % s () // \" vs. \" // manifest % version % s () return end if else if ( verbosity > 1 ) write ( iunit , out_fmt ) \"VERSION has changed presence \" end if if ( allocated ( cached % revision ) . and . allocated ( manifest % revision )) then if ( cached % revision /= manifest % revision ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"REVISION has changed: \" // cached % revision // \" vs. \" // manifest % revision return end if else if ( verbosity > 1 ) write ( iunit , out_fmt ) \"REVISION has changed presence \" end if if ( allocated ( cached % proj_dir ) . and . allocated ( manifest % proj_dir )) then if ( cached % proj_dir /= manifest % proj_dir ) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PROJECT DIR has changed: \" // cached % proj_dir // \" vs. \" // manifest % proj_dir return end if else if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PROJECT DIR has changed presence \" end if if ( allocated ( cached % preprocess ) . eqv . allocated ( manifest % preprocess )) then if ( allocated ( cached % preprocess )) then if ( size ( cached % preprocess ) /= size ( manifest % preprocess )) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PREPROCESS has changed size\" return end if do ip = 1 , size ( cached % preprocess ) if (. not .( cached % preprocess ( ip ) == manifest % preprocess ( ip ))) then if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PREPROCESS config has changed\" return end if end do endif else if ( verbosity > 1 ) write ( iunit , out_fmt ) \"PREPROCESS has changed presence \" return end if !> All checks passed: the two dependencies have no differences has_changed = . false . end function dependency_has_changed !> Check that two dependency nodes are equal logical function dependency_node_is_same ( this , that ) class ( dependency_node_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that dependency_node_is_same = . false . select type ( other => that ) type is ( dependency_node_t ) ! Base class must match if (. not .( this % dependency_config_t == other % dependency_config_t )) return ! Extension must match if (. not .( this % done . eqv . other % done )) return if (. not .( this % update . eqv . other % update )) return if (. not .( this % cached . eqv . other % cached )) return if (. not .( this % proj_dir == other % proj_dir )) return if (. not .( this % revision == other % revision )) return if (. not .( allocated ( this % version ). eqv . allocated ( other % version ))) return if ( allocated ( this % version )) then if (. not .( this % version == other % version )) return endif class default ! Not the same type return end select !> All checks passed! dependency_node_is_same = . true . end function dependency_node_is_same !> Dump dependency to toml table subroutine node_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_node_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr ! Dump parent class call self % dependency_config_t % dump_to_toml ( table , error ) if ( allocated ( error )) return if ( allocated ( self % version )) then call set_string ( table , \"version\" , self % version % s (), error , 'dependency_node_t' ) if ( allocated ( error )) return endif call set_string ( table , \"proj-dir\" , self % proj_dir , error , 'dependency_node_t' ) if ( allocated ( error )) return call set_string ( table , \"revision\" , self % revision , error , 'dependency_node_t' ) if ( allocated ( error )) return call set_value ( table , \"done\" , self % done , error , 'dependency_node_t' ) if ( allocated ( error )) return call set_value ( table , \"update\" , self % update , error , 'dependency_node_t' ) if ( allocated ( error )) return call set_value ( table , \"cached\" , self % cached , error , 'dependency_node_t' ) if ( allocated ( error )) return end subroutine node_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine node_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_node_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables character ( len = :), allocatable :: version integer :: ierr call destroy_dependency_node ( self ) ! Load parent class call self % dependency_config_t % load_from_toml ( table , error ) if ( allocated ( error )) return call get_value ( table , \"done\" , self % done , error , 'dependency_node_t' ) if ( allocated ( error )) return call get_value ( table , \"update\" , self % update , error , 'dependency_node_t' ) if ( allocated ( error )) return call get_value ( table , \"cached\" , self % cached , error , 'dependency_node_t' ) if ( allocated ( error )) return call get_value ( table , \"proj-dir\" , self % proj_dir ) call get_value ( table , \"revision\" , self % revision ) call get_value ( table , \"version\" , version ) if ( allocated ( version )) then allocate ( self % version ) call new_version ( self % version , version , error ) if ( allocated ( error )) then error % message = 'dependency_node_t: version error from TOML table - ' // error % message return endif end if end subroutine node_load_from_toml !> Destructor elemental subroutine destroy_dependency_node ( self ) class ( dependency_node_t ), intent ( inout ) :: self integer :: ierr call dependency_destroy ( self ) deallocate ( self % version , stat = ierr ) deallocate ( self % proj_dir , stat = ierr ) deallocate ( self % revision , stat = ierr ) self % done = . false . self % update = . false . self % cached = . false . end subroutine destroy_dependency_node !> Check that two dependency trees are equal logical function dependency_tree_is_same ( this , that ) class ( dependency_tree_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii dependency_tree_is_same = . false . select type ( other => that ) type is ( dependency_tree_t ) if (. not .( this % unit == other % unit )) return if (. not .( this % verbosity == other % verbosity )) return if (. not .( this % dep_dir == other % dep_dir )) return if (. not .( this % ndep == other % ndep )) return if (. not .( allocated ( this % dep ). eqv . allocated ( other % dep ))) return if ( allocated ( this % dep )) then if (. not .( size ( this % dep ) == size ( other % dep ))) return do ii = 1 , size ( this % dep ) if (. not .( this % dep ( ii ) == other % dep ( ii ))) return end do endif if (. not .( this % cache == other % cache )) return class default ! Not the same type return end select !> All checks passed! dependency_tree_is_same = . true . end function dependency_tree_is_same !> Dump dependency to toml table subroutine tree_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_tree_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii type ( toml_table ), pointer :: ptr_deps , ptr character ( 27 ) :: unnamed call set_value ( table , \"unit\" , self % unit , error , 'dependency_tree_t' ) if ( allocated ( error )) return call set_value ( table , \"verbosity\" , self % verbosity , error , 'dependency_tree_t' ) if ( allocated ( error )) return call set_string ( table , \"dep-dir\" , self % dep_dir , error , 'dependency_tree_t' ) if ( allocated ( error )) return call set_string ( table , \"cache\" , self % cache , error , 'dependency_tree_t' ) if ( allocated ( error )) return call set_value ( table , \"ndep\" , self % ndep , error , 'dependency_tree_t' ) if ( allocated ( error )) return if ( allocated ( self % dep )) then ! Create dependency table call add_table ( table , \"dependencies\" , ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , \"dependency_tree_t cannot create dependency table \" ) return end if do ii = 1 , size ( self % dep ) associate ( dep => self % dep ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( dep % name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_deps , trim ( unnamed ), ptr ) else call add_table ( ptr_deps , dep % name , ptr ) end if if (. not . associated ( ptr )) then call fatal_error ( error , \"dependency_tree_t cannot create entry for dependency \" // dep % name ) return end if call dep % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do endif 1 format ( 'UNNAMED_DEPENDENCY_' , i0 ) end subroutine tree_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine tree_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( dependency_tree_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables type ( toml_key ), allocatable :: keys (:), dep_keys (:) type ( toml_table ), pointer :: ptr_deps , ptr integer :: ii , jj , ierr call table % get_keys ( keys ) call get_value ( table , \"unit\" , self % unit , error , 'dependency_tree_t' ) if ( allocated ( error )) return call get_value ( table , \"verbosity\" , self % verbosity , error , 'dependency_tree_t' ) if ( allocated ( error )) return call get_value ( table , \"ndep\" , self % ndep , error , 'dependency_tree_t' ) if ( allocated ( error )) return call get_value ( table , \"dep-dir\" , self % dep_dir ) call get_value ( table , \"cache\" , self % cache ) find_deps_table : do ii = 1 , size ( keys ) if ( keys ( ii )% key == \"dependencies\" ) then call get_value ( table , keys ( ii ), ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , 'dependency_tree_t: error retrieving dependency table from TOML table' ) return end if !> Read all dependencies call ptr_deps % get_keys ( dep_keys ) call resize ( self % dep , size ( dep_keys )) do jj = 1 , size ( dep_keys ) call get_value ( ptr_deps , dep_keys ( jj ), ptr ) call self % dep ( jj )% load_from_toml ( ptr , error ) if ( allocated ( error )) return end do exit find_deps_table endif end do find_deps_table end subroutine tree_load_from_toml end module fpm_dependency","tags":"","loc":"sourcefile/dependency.f90~2.html"},{"title":"fpm_pkg_config.f90 – Fortran-lang/fpm","text":"Source Code !># The fpm interface to pkg-config !> !> This module contains wrapper functions to interface with a pkg-config installation. !> module fpm_pkg_config use fpm_strings , only : string_t , str_begins_with_str , len_trim , remove_newline_characters , & split use fpm_error , only : error_t , fatal_error , fpm_stop use fpm_filesystem , only : get_temp_filename , getline use fpm_environment , only : get_env , os_is_unix , set_env , delete_env use shlex_module , only : shlex_split => split implicit none private public :: assert_pkg_config public :: pkgcfg_get_version public :: pkgcfg_get_libs public :: pkgcfg_get_build_flags public :: pkgcfg_has_package public :: pkgcfg_list_all public :: run_wrapper contains !> Check whether pkg-config is available on the local system logical function assert_pkg_config () integer :: exitcode logical :: success type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), args = [ string_t ( '-h' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) assert_pkg_config = exitcode == 0 . and . success end function assert_pkg_config !> Get package version from pkg-config type ( string_t ) function pkgcfg_get_version ( package , error ) result ( screen ) !> Package name character ( * ), intent ( in ) :: package !> Error handler type ( error_t ), allocatable , intent ( out ) :: error integer :: exitcode logical :: success type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( package ), string_t ( '--modversion' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) screen = log else screen = string_t ( \"\" ) end if end function pkgcfg_get_version !> Check if pkgcfg has package logical function pkgcfg_has_package ( name ) result ( success ) !> Package name character ( * ), intent ( in ) :: name integer :: exitcode logical :: cmdok type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( name ), string_t ( '--exists' )], & exitcode = exitcode , cmd_success = cmdok , screen_output = log ) !> pkg-config --exists returns 0 only if the package exists success = cmdok . and . exitcode == 0 end function pkgcfg_has_package !> Get package libraries from pkg-config function pkgcfg_get_libs ( package , error ) result ( libraries ) !> Package name character ( * ), intent ( in ) :: package !> Error handler type ( error_t ), allocatable , intent ( out ) :: error !> A list of libraries type ( string_t ), allocatable :: libraries (:) integer :: exitcode , nlib , i logical :: success character ( len = :), allocatable :: tokens (:) type ( string_t ) :: log call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( package ), string_t ( '--libs' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) ! Split all arguments tokens = shlex_split ( log % s ) nlib = size ( tokens ) allocate ( libraries ( nlib )) do i = 1 , nlib libraries ( i ) = string_t ( trim ( adjustl ( tokens ( i )))) end do else allocate ( libraries ( 0 )) call fatal_error ( error , 'cannot get <' // package // '> libraries from pkg-config' ) end if end function pkgcfg_get_libs !> Return whole list of available pkg-cfg packages function pkgcfg_list_all ( error , descriptions ) result ( modules ) !> Error handler type ( error_t ), allocatable , intent ( out ) :: error !> A list of all available packages type ( string_t ), allocatable :: modules (:) !> An optional list of package descriptions type ( string_t ), optional , allocatable , intent ( out ) :: descriptions (:) integer :: exitcode , i , spc logical :: success character ( len = :), allocatable :: lines (:) type ( string_t ) :: log type ( string_t ), allocatable :: mods (:), descr (:) character ( * ), parameter :: CRLF = achar ( 13 ) // new_line ( 'a' ) call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( '--list-all' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if (. not .( success . and . exitcode == 0 )) then call fatal_error ( error , 'cannot get pkg-config modules' ) allocate ( modules ( 0 )) return end if !> Extract list call split ( log % s , lines , CRLF ) allocate ( mods ( size ( lines )), descr ( size ( lines ))) do i = 1 , size ( lines ) ! Module names have no spaces spc = index ( lines ( i ), ' ' ) if ( spc > 0 ) then mods ( i ) = string_t ( trim ( adjustl ( lines ( i )( 1 : spc )))) descr ( i ) = string_t ( trim ( adjustl ( lines ( i )( spc + 1 :)))) else mods ( i ) = string_t ( trim ( adjustl ( lines ( i )))) descr ( i ) = string_t ( \"\" ) end if end do call move_alloc ( from = mods , to = modules ) if ( present ( descriptions )) call move_alloc ( from = descr , to = descriptions ) end function pkgcfg_list_all !> Get build flags (option to include flags from system directories, that !> gfortran does not look into by default) function pkgcfg_get_build_flags ( name , allow_system , error ) result ( flags ) !> Package name character ( * ), intent ( in ) :: name !> Should pkg-config look in system paths? This is necessary for gfortran !> that doesn't otherwise look into them logical , intent ( in ) :: allow_system !> Error flag type ( error_t ), allocatable , intent ( out ) :: error !> List of compile flags type ( string_t ), allocatable :: flags (:) integer :: exitcode , i , nlib logical :: old_had , success , old_allow character (:), allocatable :: old , tokens (:) type ( string_t ) :: log ! Check if the current environment includes system flags old = get_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , default = 'ERROR' ) old_had = old /= 'ERROR' old_allow = merge ( old == '1' ,. false ., old_had ) ! Set system flags success = set_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , value = merge ( '1' , '0' , allow_system )) if (. not . success ) then call fatal_error ( error , 'Cannot get pkg-config build flags: environment variable error.' ) return end if ! Now run wrapper call run_wrapper ( wrapper = string_t ( 'pkg-config' ), & args = [ string_t ( name ), string_t ( '--cflags' )], & exitcode = exitcode , cmd_success = success , screen_output = log ) if ( success . and . exitcode == 0 ) then call remove_newline_characters ( log ) ! Split all arguments tokens = shlex_split ( log % s ) nlib = size ( tokens ) allocate ( flags ( nlib )) do i = 1 , nlib flags ( i ) = string_t ( trim ( adjustl ( tokens ( i )))) end do else allocate ( flags ( 0 )) call fatal_error ( error , 'cannot get <' // name // '> build flags from pkg-config' ) end if ! Restore environment variable if ( old_had ) then success = set_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' , value = old ) else success = delete_env ( 'PKG_CONFIG_ALLOW_SYSTEM_CFLAGS' ) end if if (. not . success ) then call fatal_error ( error , 'Cannot get pkg-config build flags: environment variable error.' ) return end if end function pkgcfg_get_build_flags !> Simple call to execute_command_line involving one mpi* wrapper subroutine run_wrapper ( wrapper , args , verbose , exitcode , cmd_success , screen_output ) type ( string_t ), intent ( in ) :: wrapper type ( string_t ), intent ( in ), optional :: args (:) logical , intent ( in ), optional :: verbose integer , intent ( out ), optional :: exitcode logical , intent ( out ), optional :: cmd_success type ( string_t ), intent ( out ), optional :: screen_output logical :: echo_local character (:), allocatable :: redirect_str , command , redirect , line integer :: iunit , iarg , stat , cmdstat if ( present ( verbose )) then echo_local = verbose else echo_local = . false . end if ! No redirection and non-verbose output if ( present ( screen_output )) then redirect = get_temp_filename () redirect_str = \">\" // redirect // \" 2>&1\" else if ( os_is_unix ()) then redirect_str = \" >/dev/null 2>&1\" else redirect_str = \" >NUL 2>&1\" end if end if ! Empty command if ( len_trim ( wrapper ) <= 0 ) then if ( echo_local ) print * , '+ ' if ( present ( exitcode )) exitcode = 0 if ( present ( cmd_success )) cmd_success = . true . if ( present ( screen_output )) screen_output = string_t ( \"\" ) return end if ! Init command command = trim ( wrapper % s ) add_arguments : if ( present ( args )) then do iarg = 1 , size ( args ) if ( len_trim ( args ( iarg )) <= 0 ) cycle command = trim ( command ) // ' ' // args ( iarg )% s end do endif add_arguments if ( echo_local ) print * , '+ ' , command ! Test command call execute_command_line ( command // redirect_str , exitstat = stat , cmdstat = cmdstat ) ! Command successful? if ( present ( cmd_success )) cmd_success = cmdstat == 0 ! Program exit code? if ( present ( exitcode )) exitcode = stat ! Want screen output? if ( present ( screen_output ) . and . cmdstat == 0 ) then allocate ( character ( len = 0 ) :: screen_output % s ) open ( newunit = iunit , file = redirect , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit screen_output % s = screen_output % s // new_line ( 'a' ) // line if ( echo_local ) write ( * , '(A)' ) trim ( line ) end do ! Close and delete file close ( iunit , status = 'delete' ) else call fpm_stop ( 1 , 'cannot read temporary file from successful MPI wrapper' ) endif end if end subroutine run_wrapper end module fpm_pkg_config","tags":"","loc":"sourcefile/fpm_pkg_config.f90.html"},{"title":"preprocess.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for preprocessing. !> !> A preprocess table can currently have the following fields !> !> ```toml !> [preprocess] !> [preprocess.cpp] !> suffixes = [\"F90\", \"f90\"] !> directories = [\"src/feature1\", \"src/models\"] !> macros = [] !> ``` module fpm_manifest_preprocess use fpm_error , only : error_t , syntax_error use fpm_strings , only : string_t , operator ( == ) use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list , serializable_t , set_value , set_list , & set_string use , intrinsic :: iso_fortran_env , only : stderr => error_unit implicit none private public :: preprocess_config_t , new_preprocess_config , new_preprocessors , operator ( == ) !> Configuration meta data for a preprocessor type , extends ( serializable_t ) :: preprocess_config_t !> Name of the preprocessor character ( len = :), allocatable :: name !> Suffixes of the files to be preprocessed type ( string_t ), allocatable :: suffixes (:) !> Directories to search for files to be preprocessed type ( string_t ), allocatable :: directories (:) !> Macros to be defined for the preprocessor type ( string_t ), allocatable :: macros (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => preprocess_is_same procedure :: dump_to_toml procedure :: load_from_toml !> Operations procedure :: destroy procedure :: add_config !> Properties procedure :: is_cpp procedure :: is_fypp end type preprocess_config_t character ( * ), parameter , private :: class_name = 'preprocess_config_t' contains !> Construct a new preprocess configuration from TOML data structure subroutine new_preprocess_config ( self , table , error ) !> Instance of the preprocess configuration type ( preprocess_config_t ), intent ( out ) :: self !> Instance of the TOML data structure. type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call table % get_key ( self % name ) call get_list ( table , \"suffixes\" , self % suffixes , error ) if ( allocated ( error )) return call get_list ( table , \"directories\" , self % directories , error ) if ( allocated ( error )) return call get_list ( table , \"macros\" , self % macros , error ) if ( allocated ( error )) return end subroutine new_preprocess_config !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure. type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( inout ) :: error character ( len = :), allocatable :: name type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_key ( name ) call table % get_keys ( list ) do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) !> Valid keys. case ( \"suffixes\" , \"directories\" , \"macros\" ) case default call syntax_error ( error , \"Key '\" // list ( ikey )% key // \"' not allowed in preprocessor '\" // name // \"'.\" ); exit end select end do end subroutine check !> Construct new preprocess array from a TOML data structure. subroutine new_preprocessors ( preprocessors , table , error ) !> Instance of the preprocess configuration type ( preprocess_config_t ), allocatable , intent ( out ) :: preprocessors (:) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: node type ( toml_key ), allocatable :: list (:) integer :: iprep , stat call table % get_keys ( list ) ! An empty table is not allowed if ( size ( list ) == 0 ) then call syntax_error ( error , \"No preprocessors defined\" ) end if allocate ( preprocessors ( size ( list ))) do iprep = 1 , size ( list ) call get_value ( table , list ( iprep )% key , node , stat = stat ) if ( stat /= toml_stat % success ) then call syntax_error ( error , \"Preprocessor \" // list ( iprep )% key // \" must be a table entry\" ) exit end if call new_preprocess_config ( preprocessors ( iprep ), node , error ) if ( allocated ( error )) exit end do end subroutine new_preprocessors !> Write information on this instance subroutine info ( self , unit , verbosity ) !> Instance of the preprocess configuration class ( preprocess_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ilink character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Preprocessor\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % suffixes )) then write ( unit , fmt ) \" - suffixes\" do ilink = 1 , size ( self % suffixes ) write ( unit , fmt ) \" - \" // self % suffixes ( ilink )% s end do end if if ( allocated ( self % directories )) then write ( unit , fmt ) \" - directories\" do ilink = 1 , size ( self % directories ) write ( unit , fmt ) \" - \" // self % directories ( ilink )% s end do end if if ( allocated ( self % macros )) then write ( unit , fmt ) \" - macros\" do ilink = 1 , size ( self % macros ) write ( unit , fmt ) \" - \" // self % macros ( ilink )% s end do end if end subroutine info logical function preprocess_is_same ( this , that ) class ( preprocess_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: istr preprocess_is_same = . false . select type ( other => that ) type is ( preprocess_config_t ) if ( allocated ( this % name ). neqv . allocated ( other % name )) return if ( allocated ( this % name )) then if (. not .( this % name == other % name )) return endif if (. not .( this % suffixes == other % suffixes )) return if (. not .( this % directories == other % directories )) return if (. not .( this % macros == other % macros )) return class default ! Not the same type return end select !> All checks passed! preprocess_is_same = . true . end function preprocess_is_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( preprocess_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_string ( table , \"name\" , self % name , error ) if ( allocated ( error )) return call set_list ( table , \"suffixes\" , self % suffixes , error ) if ( allocated ( error )) return call set_list ( table , \"directories\" , self % directories , error ) if ( allocated ( error )) return call set_list ( table , \"macros\" , self % macros , error ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( preprocess_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"name\" , self % name ) call get_list ( table , \"suffixes\" , self % suffixes , error ) if ( allocated ( error )) return call get_list ( table , \"directories\" , self % directories , error ) if ( allocated ( error )) return call get_list ( table , \"macros\" , self % macros , error ) if ( allocated ( error )) return end subroutine load_from_toml !> Clean preprocessor structure elemental subroutine destroy ( this ) class ( preprocess_config_t ), intent ( inout ) :: this if ( allocated ( this % name )) deallocate ( this % name ) if ( allocated ( this % suffixes )) deallocate ( this % suffixes ) if ( allocated ( this % directories )) deallocate ( this % directories ) if ( allocated ( this % macros )) deallocate ( this % macros ) end subroutine destroy !> Add preprocessor settings subroutine add_config ( this , that ) class ( preprocess_config_t ), intent ( inout ) :: this type ( preprocess_config_t ), intent ( in ) :: that if (. not . that % is_cpp ()) then write ( stderr , '(a)' ) 'Warning: Preprocessor ' // that % name // & ' is not supported; will ignore it' return end if if (. not . allocated ( this % name )) this % name = that % name ! Add macros if ( allocated ( that % macros )) then if ( allocated ( this % macros )) then this % macros = [ this % macros , that % macros ] else allocate ( this % macros , source = that % macros ) end if endif ! Add suffixes if ( allocated ( that % suffixes )) then if ( allocated ( this % suffixes )) then this % suffixes = [ this % suffixes , that % suffixes ] else allocate ( this % suffixes , source = that % suffixes ) end if endif ! Add directories if ( allocated ( that % directories )) then if ( allocated ( this % directories )) then this % directories = [ this % directories , that % directories ] else allocate ( this % directories , source = that % directories ) end if endif end subroutine add_config ! Check cpp logical function is_cpp ( this ) class ( preprocess_config_t ), intent ( in ) :: this is_cpp = . false . if ( allocated ( this % name )) is_cpp = this % name == \"cpp\" end function is_cpp ! Check cpp logical function is_fypp ( this ) class ( preprocess_config_t ), intent ( in ) :: this is_fypp = . false . if ( allocated ( this % name )) is_fypp = this % name == \"fypp\" end function is_fypp end module fpm_manifest_preprocess","tags":"","loc":"sourcefile/preprocess.f90.html"},{"title":"fpm_model.f90 – Fortran-lang/fpm","text":"Source Code !># The fpm package model !> !> Defines the fpm model data types which encapsulate all information !> required to correctly build a package and its dependencies. !> !> The process (see `[[build_model(subroutine)]]`) for generating a valid `[[fpm_model]]` involves !> source files discovery ([[fpm_sources]]) and parsing ([[fpm_source_parsing]]). !> !> Once a valid `[[fpm_model]]` has been constructed, it may be passed to `[[fpm_targets:targets_from_sources]]` to !> generate a list of build targets for the backend. !> !>### Enumerations !> !> __Source type:__ `FPM_UNIT_*` !> Describes the type of source file — determines build target generation !> !> The logical order of precedence for assigning `unit_type` is as follows: !> !>``` !> if source-file contains program then !> unit_type = FPM_UNIT_PROGRAM !> else if source-file contains non-module subroutine/function then !> unit_type = FPM_UNIT_SUBPROGRAM !> else if source-file contains submodule then !> unit_type = FPM_UNIT_SUBMODULE !> else if source-file contains module then !> unit_type = FPM_UNIT_MODULE !> end if !>``` !> !> @note A source file is only designated `FPM_UNIT_MODULE` if it **only** contains modules - no non-module subprograms. !> (This allows tree-shaking/pruning of build targets based on unused module dependencies.) !> !> __Source scope:__ `FPM_SCOPE_*` !> Describes the scoping rules for using modules — controls module dependency resolution !> module fpm_model use iso_fortran_env , only : int64 use fpm_compiler , only : compiler_t , archiver_t , debug use fpm_dependency , only : dependency_tree_t use fpm_strings , only : string_t , str , len_trim , upper , operator ( == ) use fpm_toml , only : serializable_t , toml_table , toml_stat , set_value , set_list , get_value , & & get_list , add_table , toml_key , add_array , set_string use fpm_error , only : error_t , fatal_error use fpm_manifest_preprocess , only : preprocess_config_t implicit none private public :: fpm_model_t , srcfile_t , show_model , fortran_features_t , package_t public :: FPM_UNIT_UNKNOWN , FPM_UNIT_PROGRAM , FPM_UNIT_MODULE , & FPM_UNIT_SUBMODULE , FPM_UNIT_SUBPROGRAM , FPM_UNIT_CSOURCE , & FPM_UNIT_CHEADER , FPM_SCOPE_UNKNOWN , FPM_SCOPE_LIB , & FPM_SCOPE_DEP , FPM_SCOPE_APP , FPM_SCOPE_EXAMPLE , FPM_SCOPE_TEST , & FPM_UNIT_CPPSOURCE , FPM_SCOPE_NAME , FPM_UNIT_NAME !> Source type unknown integer , parameter :: FPM_UNIT_UNKNOWN = - 1 !> Source contains a fortran program integer , parameter :: FPM_UNIT_PROGRAM = 1 !> Source **only** contains one or more fortran modules integer , parameter :: FPM_UNIT_MODULE = 2 !> Source contains one or more fortran submodules integer , parameter :: FPM_UNIT_SUBMODULE = 3 !> Source contains one or more fortran subprogram not within modules integer , parameter :: FPM_UNIT_SUBPROGRAM = 4 !> Source type is c source file integer , parameter :: FPM_UNIT_CSOURCE = 5 !> Source type is c header file integer , parameter :: FPM_UNIT_CHEADER = 6 !> Souce type is c++ source file. integer , parameter :: FPM_UNIT_CPPSOURCE = 7 !> Source has no module-use scope integer , parameter :: FPM_SCOPE_UNKNOWN = - 1 !> Module-use scope is library/dependency modules only integer , parameter :: FPM_SCOPE_LIB = 1 !> Module-use scope is library/dependency modules only integer , parameter :: FPM_SCOPE_DEP = 2 !> Module-use scope is library/dependency and app modules integer , parameter :: FPM_SCOPE_APP = 3 !> Module-use scope is library/dependency and test modules integer , parameter :: FPM_SCOPE_TEST = 4 integer , parameter :: FPM_SCOPE_EXAMPLE = 5 !> Enabled Fortran language features type , extends ( serializable_t ) :: fortran_features_t !> Use default implicit typing logical :: implicit_typing = . false . !> Use implicit external interface logical :: implicit_external = . false . !> Form to use for all Fortran sources character (:), allocatable :: source_form contains !> Serialization interface procedure :: serializable_is_same => fft_is_same procedure :: dump_to_toml => fft_dump_to_toml procedure :: load_from_toml => fft_load_from_toml end type fortran_features_t !> Type for describing a source file type , extends ( serializable_t ) :: srcfile_t !> File path relative to cwd character (:), allocatable :: file_name !> Name of executable for FPM_UNIT_PROGRAM character (:), allocatable :: exe_name !> Target module-use scope integer :: unit_scope = FPM_SCOPE_UNKNOWN !> Modules provided by this source file (lowerstring) type ( string_t ), allocatable :: modules_provided (:) !> Type of source unit integer :: unit_type = FPM_UNIT_UNKNOWN !> Parent modules (submodules only) type ( string_t ), allocatable :: parent_modules (:) !> Modules USEd by this source file (lowerstring) type ( string_t ), allocatable :: modules_used (:) !> Files INCLUDEd by this source file type ( string_t ), allocatable :: include_dependencies (:) !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> Current hash integer ( int64 ) :: digest contains !> Serialization interface procedure :: serializable_is_same => srcfile_is_same procedure :: dump_to_toml => srcfile_dump_to_toml procedure :: load_from_toml => srcfile_load_from_toml end type srcfile_t !> Type for describing a single package type , extends ( serializable_t ) :: package_t !> Name of package character (:), allocatable :: name !> Array of sources type ( srcfile_t ), allocatable :: sources (:) !> List of macros. type ( preprocess_config_t ) :: preprocess !> Package version number. character (:), allocatable :: version !> Module naming conventions logical :: enforce_module_names = . false . !> Prefix for all module names type ( string_t ) :: module_prefix !> Language features type ( fortran_features_t ) :: features contains !> Serialization interface procedure :: serializable_is_same => package_is_same procedure :: dump_to_toml => package_dump_to_toml procedure :: load_from_toml => package_load_from_toml end type package_t !> Type describing everything required to build !> the root package and its dependencies. type , extends ( serializable_t ) :: fpm_model_t !> Name of root package character (:), allocatable :: package_name !> Array of packages (including the root package) type ( package_t ), allocatable :: packages (:) !> Compiler object type ( compiler_t ) :: compiler !> Archiver object type ( archiver_t ) :: archiver !> Command line flags passed to fortran for compilation character (:), allocatable :: fortran_compile_flags !> Command line flags passed to C for compilation character (:), allocatable :: c_compile_flags !> Command line flags passed to C++ for compilation character (:), allocatable :: cxx_compile_flags !> Command line flags passed to the linker character (:), allocatable :: link_flags !> Base directory for build character (:), allocatable :: build_prefix !> Include directories type ( string_t ), allocatable :: include_dirs (:) !> Native libraries to link against type ( string_t ), allocatable :: link_libraries (:) !> External modules used type ( string_t ), allocatable :: external_modules (:) !> Project dependencies type ( dependency_tree_t ) :: deps !> Whether tests should be added to the build list logical :: include_tests = . true . !> Whether module names should be prefixed with the package name logical :: enforce_module_names = . false . !> Prefix for all module names type ( string_t ) :: module_prefix contains !> Serialization interface procedure :: serializable_is_same => model_is_same procedure :: dump_to_toml => model_dump_to_toml procedure :: load_from_toml => model_load_from_toml end type fpm_model_t contains function info_package ( p ) result ( s ) ! Returns representation of package_t type ( package_t ), intent ( in ) :: p character (:), allocatable :: s integer :: i s = s // 'package_t(' s = s // 'name=\"' // p % name // '\"' s = s // ', sources=[' do i = 1 , size ( p % sources ) s = s // info_srcfile ( p % sources ( i )) if ( i < size ( p % sources )) s = s // \", \" end do s = s // \"]\" ! Print module naming convention s = s // ', enforce_module_names=\"' // merge ( 'T' , 'F' , p % enforce_module_names ) // '\"' ! Print custom prefix if ( p % enforce_module_names . and . len_trim ( p % module_prefix ) > 0 ) & s = s // ', custom_prefix=\"' // p % module_prefix % s // '\"' s = s // \")\" end function info_package function info_srcfile ( source ) result ( s ) type ( srcfile_t ), intent ( in ) :: source character (:), allocatable :: s integer :: i !type srcfile_t s = \"srcfile_t(\" ! character(:), allocatable :: file_name s = s // 'file_name=\"' // source % file_name // '\"' ! character(:), allocatable :: exe_name s = s // ', exe_name=\"' // source % exe_name // '\"' ! integer :: unit_scope = FPM_SCOPE_UNKNOWN s = s // ', unit_scope=\"' // FPM_SCOPE_NAME ( source % unit_scope ) // '\"' ! type(string_t), allocatable :: modules_provided(:) s = s // \", modules_provided=[\" do i = 1 , size ( source % modules_provided ) s = s // '\"' // source % modules_provided ( i )% s // '\"' if ( i < size ( source % modules_provided )) s = s // \", \" end do s = s // \"]\" s = s // \", parent_modules=[\" do i = 1 , size ( source % parent_modules ) s = s // '\"' // source % parent_modules ( i )% s // '\"' if ( i < size ( source % parent_modules )) s = s // \", \" end do s = s // \"]\" ! integer :: unit_type = FPM_UNIT_UNKNOWN s = s // ', unit_type=\"' // FPM_UNIT_NAME ( source % unit_type ) // '\"' ! type(string_t), allocatable :: modules_used(:) s = s // \", modules_used=[\" do i = 1 , size ( source % modules_used ) s = s // '\"' // source % modules_used ( i )% s // '\"' if ( i < size ( source % modules_used )) s = s // \", \" end do s = s // \"]\" ! type(string_t), allocatable :: include_dependencies(:) s = s // \", include_dependencies=[\" do i = 1 , size ( source % include_dependencies ) s = s // '\"' // source % include_dependencies ( i )% s // '\"' if ( i < size ( source % include_dependencies )) s = s // \", \" end do s = s // \"]\" ! type(string_t), allocatable :: link_libraries(:) s = s // \", link_libraries=[\" do i = 1 , size ( source % link_libraries ) s = s // '\"' // source % link_libraries ( i )% s // '\"' if ( i < size ( source % link_libraries )) s = s // \", \" end do s = s // \"]\" ! integer(int64) :: digest s = s // \", digest=\" // str ( source % digest ) !end type srcfile_t s = s // \")\" end function info_srcfile function info_srcfile_short ( source ) result ( s ) ! Prints a shortened version of srcfile_t type ( srcfile_t ), intent ( in ) :: source character (:), allocatable :: s s = \"srcfile_t(\" s = s // 'file_name=\"' // source % file_name // '\"' s = s // \", ...)\" end function info_srcfile_short function info_model ( model ) result ( s ) type ( fpm_model_t ), intent ( in ) :: model character (:), allocatable :: s integer :: i !type :: fpm_model_t s = \"fpm_model_t(\" ! character(:), allocatable :: package_name s = s // 'package_name=\"' // model % package_name // '\"' ! type(srcfile_t), allocatable :: sources(:) s = s // \", packages=[\" do i = 1 , size ( model % packages ) s = s // info_package ( model % packages ( i )) if ( i < size ( model % packages )) s = s // \", \" end do s = s // \"]\" s = s // ', compiler=(' // debug ( model % compiler ) // ')' s = s // ', archiver=(' // debug ( model % archiver ) // ')' ! character(:), allocatable :: fortran_compile_flags s = s // ', fortran_compile_flags=\"' // model % fortran_compile_flags // '\"' s = s // ', c_compile_flags=\"' // model % c_compile_flags // '\"' s = s // ', cxx_compile_flags=\"' // model % cxx_compile_flags // '\"' s = s // ', link_flags=\"' // model % link_flags // '\"' s = s // ', build_prefix=\"' // model % build_prefix // '\"' ! type(string_t), allocatable :: link_libraries(:) s = s // \", link_libraries=[\" do i = 1 , size ( model % link_libraries ) s = s // '\"' // model % link_libraries ( i )% s // '\"' if ( i < size ( model % link_libraries )) s = s // \", \" end do s = s // \"]\" ! type(string_t), allocatable :: external_modules(:) s = s // \", external_modules=[\" do i = 1 , size ( model % external_modules ) s = s // '\"' // model % external_modules ( i )% s // '\"' if ( i < size ( model % external_modules )) s = s // \", \" end do s = s // \"]\" ! type(dependency_tree_t) :: deps ! TODO: print `dependency_tree_t` properly, which should become part of the ! model, not imported from another file s = s // \", deps=dependency_tree_t(...)\" ! Print module naming convention s = s // ', enforce_module_names=\"' // merge ( 'T' , 'F' , model % enforce_module_names ) // '\"' ! Print custom prefix if ( model % enforce_module_names . and . len_trim ( model % module_prefix ) > 0 ) & s = s // ', custom_prefix=\"' // model % module_prefix % s // '\"' !end type fpm_model_t s = s // \")\" end function info_model subroutine show_model ( model ) ! Prints a human readable representation of the Model type ( fpm_model_t ), intent ( in ) :: model print * , info_model ( model ) end subroutine show_model !> Return the character name of a scope flag function FPM_SCOPE_NAME ( flag ) result ( name ) integer , intent ( in ) :: flag character ( len = :), allocatable :: name select case ( flag ) case ( FPM_SCOPE_UNKNOWN ); name = \"FPM_SCOPE_UNKNOWN\" case ( FPM_SCOPE_LIB ); name = \"FPM_SCOPE_LIB\" case ( FPM_SCOPE_DEP ); name = \"FPM_SCOPE_DEP\" case ( FPM_SCOPE_APP ); name = \"FPM_SCOPE_APP\" case ( FPM_SCOPE_TEST ); name = \"FPM_SCOPE_TEST\" case ( FPM_SCOPE_EXAMPLE ); name = \"FPM_SCOPE_EXAMPLE\" case default ; name = \"INVALID\" end select end function FPM_SCOPE_NAME !> Parse git FPM_SCOPE identifier from a string integer function parse_scope ( name ) result ( scope ) character ( len =* ), intent ( in ) :: name character ( len = len ( name )) :: uppercase !> Make it Case insensitive uppercase = upper ( name ) select case ( trim ( uppercase )) case ( \"FPM_SCOPE_UNKNOWN\" ); scope = FPM_SCOPE_UNKNOWN case ( \"FPM_SCOPE_LIB\" ); scope = FPM_SCOPE_LIB case ( \"FPM_SCOPE_DEP\" ); scope = FPM_SCOPE_DEP case ( \"FPM_SCOPE_APP\" ); scope = FPM_SCOPE_APP case ( \"FPM_SCOPE_TEST\" ); scope = FPM_SCOPE_TEST case ( \"FPM_SCOPE_EXAMPLE\" ); scope = FPM_SCOPE_EXAMPLE case default ; scope = - 9999 end select end function parse_scope !> Return the character name of a unit flag function FPM_UNIT_NAME ( flag ) result ( name ) integer , intent ( in ) :: flag character ( len = :), allocatable :: name select case ( flag ) case ( FPM_UNIT_UNKNOWN ); name = \"FPM_UNIT_UNKNOWN\" case ( FPM_UNIT_PROGRAM ); name = \"FPM_UNIT_PROGRAM\" case ( FPM_UNIT_MODULE ); name = \"FPM_UNIT_MODULE\" case ( FPM_UNIT_SUBMODULE ); name = \"FPM_UNIT_SUBMODULE\" case ( FPM_UNIT_SUBPROGRAM ); name = \"FPM_UNIT_SUBPROGRAM\" case ( FPM_UNIT_CSOURCE ); name = \"FPM_UNIT_CSOURCE\" case ( FPM_UNIT_CPPSOURCE ); name = \"FPM_UNIT_CPPSOURCE\" case ( FPM_UNIT_CHEADER ); name = \"FPM_UNIT_CHEADER\" case default ; name = \"INVALID\" end select end function FPM_UNIT_NAME !> Parse git FPM_UNIT identifier from a string integer function parse_unit ( name ) result ( unit ) character ( len =* ), intent ( in ) :: name character ( len = len ( name )) :: uppercase !> Make it Case insensitive uppercase = upper ( name ) select case ( trim ( uppercase )) case ( \"FPM_UNIT_UNKNOWN\" ); unit = FPM_UNIT_UNKNOWN case ( \"FPM_UNIT_PROGRAM\" ); unit = FPM_UNIT_PROGRAM case ( \"FPM_UNIT_MODULE\" ); unit = FPM_UNIT_MODULE case ( \"FPM_UNIT_SUBMODULE\" ); unit = FPM_UNIT_SUBMODULE case ( \"FPM_UNIT_SUBPROGRAM\" ); unit = FPM_UNIT_SUBPROGRAM case ( \"FPM_UNIT_CSOURCE\" ); unit = FPM_UNIT_CSOURCE case ( \"FPM_UNIT_CPPSOURCE\" ); unit = FPM_UNIT_CPPSOURCE case ( \"FPM_UNIT_CHEADER\" ); unit = FPM_UNIT_CHEADER case default ; unit = - 9999 end select end function parse_unit !> Check that two source files are equal logical function srcfile_is_same ( this , that ) class ( srcfile_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that srcfile_is_same = . false . select type ( other => that ) type is ( srcfile_t ) if (. not .( this % file_name == other % file_name )) return if (. not .( this % exe_name == other % exe_name )) return if (. not .( this % unit_scope == other % unit_scope )) return if (. not .( this % modules_provided == other % modules_provided )) return if (. not .( this % unit_type == other % unit_type )) return if (. not .( this % parent_modules == other % parent_modules )) return if (. not .( this % modules_used == other % modules_used )) return if (. not .( this % include_dependencies == other % include_dependencies )) return if (. not .( this % link_libraries == other % link_libraries )) return if (. not .( this % digest == other % digest )) return class default ! Not the same type return end select !> All checks passed! srcfile_is_same = . true . end function srcfile_is_same !> Dump dependency to toml table subroutine srcfile_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( srcfile_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_string ( table , \"file-name\" , self % file_name , error , 'srcfile_t' ) if ( allocated ( error )) return call set_string ( table , \"exe-name\" , self % exe_name , error , 'srcfile_t' ) if ( allocated ( error )) return call set_value ( table , \"digest\" , self % digest , error , 'srcfile_t' ) if ( allocated ( error )) return ! unit_scope and unit_type are saved as strings so the output is independent ! of the internal representation call set_string ( table , \"unit-scope\" , FPM_SCOPE_NAME ( self % unit_scope ), error , 'srcfile_t' ) if ( allocated ( error )) return call set_string ( table , \"unit-type\" , FPM_UNIT_NAME ( self % unit_type ), error , 'srcfile_t' ) if ( allocated ( error )) return call set_list ( table , \"modules-provided\" , self % modules_provided , error ) if ( allocated ( error )) return call set_list ( table , \"parent-modules\" , self % parent_modules , error ) if ( allocated ( error )) return call set_list ( table , \"modules-used\" , self % modules_used , error ) if ( allocated ( error )) return call set_list ( table , \"include-dependencies\" , self % include_dependencies , error ) if ( allocated ( error )) return call set_list ( table , \"link-libraries\" , self % link_libraries , error ) if ( allocated ( error )) return end subroutine srcfile_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine srcfile_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( srcfile_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: flag integer :: ierr call get_value ( table , \"file-name\" , self % file_name ) call get_value ( table , \"exe-name\" , self % exe_name ) call get_value ( table , \"digest\" , self % digest , error , 'srcfile_t' ) if ( allocated ( error )) return ! unit_scope and unit_type are saved as strings so the output is independent ! of the internal representation call get_value ( table , \"unit-scope\" , flag ) if ( allocated ( flag )) self % unit_scope = parse_scope ( flag ) call get_value ( table , \"unit-type\" , flag ) if ( allocated ( flag )) self % unit_type = parse_unit ( flag ) call get_list ( table , \"modules-provided\" , self % modules_provided , error ) if ( allocated ( error )) return call get_list ( table , \"parent-modules\" , self % parent_modules , error ) if ( allocated ( error )) return call get_list ( table , \"modules-used\" , self % modules_used , error ) if ( allocated ( error )) return call get_list ( table , \"include-dependencies\" , self % include_dependencies , error ) if ( allocated ( error )) return call get_list ( table , \"link-libraries\" , self % link_libraries , error ) if ( allocated ( error )) return end subroutine srcfile_load_from_toml !> Check that two fortran feature objects are equal logical function fft_is_same ( this , that ) class ( fortran_features_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that fft_is_same = . false . select type ( other => that ) type is ( fortran_features_t ) if (. not .( this % implicit_typing . eqv . other % implicit_typing )) return if (. not .( this % implicit_external . eqv . other % implicit_external )) return if (. not .( this % source_form == other % source_form )) return class default ! Not the same type return end select !> All checks passed! fft_is_same = . true . end function fft_is_same !> Dump fortran features to toml table subroutine fft_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( fortran_features_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_value ( table , \"implicit-typing\" , self % implicit_typing , error , 'fortran_features_t' ) if ( allocated ( error )) return call set_value ( table , \"implicit-external\" , self % implicit_external , error , 'fortran_features_t' ) if ( allocated ( error )) return call set_string ( table , \"source-form\" , self % source_form , error , 'fortran_features_t' ) if ( allocated ( error )) return end subroutine fft_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine fft_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( fortran_features_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call get_value ( table , \"implicit-typing\" , self % implicit_typing , error , 'fortran_features_t' ) if ( allocated ( error )) return call get_value ( table , \"implicit-external\" , self % implicit_external , error , 'fortran_features_t' ) if ( allocated ( error )) return ! Return unallocated value if not present call get_value ( table , \"source-form\" , self % source_form ) end subroutine fft_load_from_toml !> Check that two package objects are equal logical function package_is_same ( this , that ) class ( package_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii package_is_same = . false . select type ( other => that ) type is ( package_t ) if (. not .( this % name == other % name )) return if (. not .( allocated ( this % sources ). eqv . allocated ( other % sources ))) return if ( allocated ( this % sources )) then if (. not .( size ( this % sources ) == size ( other % sources ))) return do ii = 1 , size ( this % sources ) if (. not .( this % sources ( ii ) == other % sources ( ii ))) return end do end if if (. not .( this % preprocess == other % preprocess )) return if (. not .( this % version == other % version )) return !> Module naming if (. not .( this % enforce_module_names . eqv . other % enforce_module_names )) return if (. not .( this % module_prefix == other % module_prefix )) return !> Fortran features if (. not .( this % features == other % features )) return class default ! Not the same type return end select !> All checks passed! package_is_same = . true . end function package_is_same !> Dump dependency to toml table subroutine package_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( package_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii type ( toml_table ), pointer :: ptr , this_source character ( 16 ) :: src_name call set_string ( table , \"name\" , self % name , error , 'package_t' ) if ( allocated ( error )) return call set_string ( table , \"version\" , self % version , error , 'package_t' ) if ( allocated ( error )) return call set_value ( table , \"module-naming\" , self % enforce_module_names , error , 'package_t' ) if ( allocated ( error )) return call set_string ( table , \"module-prefix\" , self % module_prefix , error , 'package_t' ) if ( allocated ( error )) return !> Create a preprocessor table call add_table ( table , \"preprocess\" , ptr , error , 'package_t' ) if ( allocated ( error )) return call self % preprocess % dump_to_toml ( ptr , error ) if ( allocated ( error )) return !> Create a fortran table call add_table ( table , \"fortran\" , ptr , error , 'package_t' ) if ( allocated ( error )) return call self % features % dump_to_toml ( ptr , error ) if ( allocated ( error )) return !> Create a sources table if ( allocated ( self % sources )) then call add_table ( table , \"sources\" , ptr , error , 'package_t' ) if ( allocated ( error )) return do ii = 1 , size ( self % sources ) write ( src_name , 1 ) ii call add_table ( ptr , trim ( src_name ), this_source , error , 'package_t[source]' ) if ( allocated ( error )) return call self % sources ( ii )% dump_to_toml ( this_source , error ) if ( allocated ( error )) return end do end if 1 format ( 'src_' , i0 ) end subroutine package_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine package_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( package_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii , jj type ( toml_key ), allocatable :: keys (:), src_keys (:) type ( toml_table ), pointer :: ptr_sources , ptr , ptr_fortran , ptr_preprocess type ( error_t ), allocatable :: new_error call get_value ( table , \"name\" , self % name ) call get_value ( table , \"version\" , self % version ) call get_value ( table , \"module-naming\" , self % enforce_module_names , error , 'package_t' ) if ( allocated ( error )) return ! Return unallocated value if not present call get_value ( table , \"module-prefix\" , self % module_prefix % s ) ! Sources call table % get_keys ( keys ) find_others : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"fortran\" ) call get_value ( table , keys ( ii ), ptr_fortran ) if (. not . associated ( ptr_fortran )) then call fatal_error ( error , 'package_t: error retrieving fortran table from TOML table' ) return end if call self % features % load_from_toml ( ptr_fortran , error ) if ( allocated ( error )) return case ( \"preprocess\" ) call get_value ( table , keys ( ii ), ptr_preprocess ) if (. not . associated ( ptr_preprocess )) then call fatal_error ( error , 'package_t: error retrieving preprocess table from TOML table' ) return end if call self % preprocess % load_from_toml ( ptr_preprocess , error ) if ( allocated ( error )) return case ( \"sources\" ) call get_value ( table , keys ( ii ), ptr_sources ) if (. not . associated ( ptr_sources )) then call fatal_error ( error , 'package_t: error retrieving sources table from TOML table' ) return end if !> Read all dependencies call ptr_sources % get_keys ( src_keys ) allocate ( self % sources ( size ( src_keys ))) do jj = 1 , size ( src_keys ) call get_value ( ptr_sources , src_keys ( jj ), ptr ) call self % sources ( jj )% load_from_toml ( ptr , error ) if ( allocated ( error )) return end do case default cycle find_others end select end do find_others end subroutine package_load_from_toml !> Check that two model objects are equal logical function model_is_same ( this , that ) class ( fpm_model_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that type ( fpm_model_t ), pointer :: other integer :: ii model_is_same = . false . select type ( other => that ) type is ( fpm_model_t ) if (. not .( this % package_name == other % package_name )) return if (. not .( allocated ( this % packages ). eqv . allocated ( other % packages ))) return if ( allocated ( this % packages )) then if (. not .( size ( this % packages ) == size ( other % packages ))) return do ii = 1 , size ( this % packages ) if (. not .( this % packages ( ii ) == other % packages ( ii ))) return end do end if if (. not .( this % compiler == other % compiler )) return if (. not .( this % archiver == other % archiver )) return if (. not .( this % fortran_compile_flags == other % fortran_compile_flags )) return if (. not .( this % c_compile_flags == other % c_compile_flags )) return if (. not .( this % cxx_compile_flags == other % cxx_compile_flags )) return if (. not .( this % link_flags == other % link_flags )) return if (. not .( this % build_prefix == other % build_prefix )) return if (. not .( this % include_dirs == other % include_dirs )) return if (. not .( this % link_libraries == other % link_libraries )) return if (. not .( this % external_modules == other % external_modules )) return if (. not .( this % deps == other % deps )) return if (. not .( this % include_tests . eqv . other % include_tests )) return if (. not .( this % enforce_module_names . eqv . other % enforce_module_names )) return if (. not .( this % module_prefix == other % module_prefix )) return class default ! Not the same type return end select !> All checks passed! model_is_same = . true . end function model_is_same !> Dump dependency to toml table subroutine model_dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( fpm_model_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr , ii type ( toml_table ), pointer :: ptr , ptr_pkg character ( 27 ) :: unnamed call set_string ( table , \"package-name\" , self % package_name , error , 'fpm_model_t' ) if ( allocated ( error )) return call add_table ( table , \"compiler\" , ptr , error , 'fpm_model_t' ) if ( allocated ( error )) return call self % compiler % dump_to_toml ( ptr , error ) if ( allocated ( error )) return call add_table ( table , \"archiver\" , ptr , error , 'fpm_model_t' ) if ( allocated ( error )) return call self % archiver % dump_to_toml ( ptr , error ) if ( allocated ( error )) return call set_string ( table , \"fortran-flags\" , self % fortran_compile_flags , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"c-flags\" , self % c_compile_flags , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"cxx-flags\" , self % cxx_compile_flags , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"link-flags\" , self % link_flags , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"build-prefix\" , self % build_prefix , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_list ( table , \"include-dirs\" , self % include_dirs , error ) if ( allocated ( error )) return call set_list ( table , \"link-libraries\" , self % link_libraries , error ) if ( allocated ( error )) return call set_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return call set_value ( table , \"include-tests\" , self % include_tests , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_value ( table , \"module-naming\" , self % enforce_module_names , error , 'fpm_model_t' ) if ( allocated ( error )) return call set_string ( table , \"module-prefix\" , self % module_prefix , error , 'fpm_model_t' ) if ( allocated ( error )) return call add_table ( table , \"deps\" , ptr , error , 'fpm_model_t' ) if ( allocated ( error )) return call self % deps % dump_to_toml ( ptr , error ) if ( allocated ( error )) return !> Array of packages (including the root package) if ( allocated ( self % packages )) then ! Create packages table call add_table ( table , \"packages\" , ptr_pkg ) if (. not . associated ( ptr_pkg )) then call fatal_error ( error , \"fpm_model_t cannot create dependency table \" ) return end if do ii = 1 , size ( self % packages ) associate ( pkg => self % packages ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( pkg % name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_pkg , trim ( unnamed ), ptr , error , 'fpm_model_t[package]' ) else call add_table ( ptr_pkg , pkg % name , ptr , error , 'fpm_model_t[package]' ) end if if ( allocated ( error )) return call pkg % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do end if 1 format ( 'UNNAMED_PACKAGE_' , i0 ) end subroutine model_dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine model_load_from_toml ( self , table , error ) !> Instance of the serializable object class ( fpm_model_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: keys (:), pkg_keys (:) integer :: ierr , ii , jj type ( toml_table ), pointer :: ptr , ptr_pkg call table % get_keys ( keys ) call get_value ( table , \"package-name\" , self % package_name ) call get_value ( table , \"fortran-flags\" , self % fortran_compile_flags ) call get_value ( table , \"c-flags\" , self % c_compile_flags ) call get_value ( table , \"cxx-flags\" , self % cxx_compile_flags ) call get_value ( table , \"link-flags\" , self % link_flags ) call get_value ( table , \"build-prefix\" , self % build_prefix ) if ( allocated ( self % packages )) deallocate ( self % packages ) sub_deps : do ii = 1 , size ( keys ) select case ( keys ( ii )% key ) case ( \"compiler\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'fpm_model_t: error retrieving compiler table' ) return end if call self % compiler % load_from_toml ( ptr , error ) if ( allocated ( error )) return case ( \"archiver\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'fpm_model_t: error retrieving archiver table' ) return end if call self % archiver % load_from_toml ( ptr , error ) if ( allocated ( error )) return case ( \"deps\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'fpm_model_t: error retrieving dependency tree table' ) return end if call self % deps % load_from_toml ( ptr , error ) if ( allocated ( error )) return case ( \"packages\" ) call get_value ( table , keys ( ii ), ptr ) if (. not . associated ( ptr )) then call fatal_error ( error , 'fpm_model_t: error retrieving packages table' ) return end if !> Read all packages call ptr % get_keys ( pkg_keys ) allocate ( self % packages ( size ( pkg_keys ))) do jj = 1 , size ( pkg_keys ) call get_value ( ptr , pkg_keys ( jj ), ptr_pkg ) call self % packages ( jj )% load_from_toml ( ptr_pkg , error ) if ( allocated ( error )) return end do case default cycle sub_deps end select end do sub_deps call get_list ( table , \"include-dirs\" , self % include_dirs , error ) if ( allocated ( error )) return call get_list ( table , \"link-libraries\" , self % link_libraries , error ) if ( allocated ( error )) return call get_list ( table , \"external-modules\" , self % external_modules , error ) if ( allocated ( error )) return call get_value ( table , \"include-tests\" , self % include_tests , error , 'fpm_model_t' ) if ( allocated ( error )) return call get_value ( table , \"module-naming\" , self % enforce_module_names , error , 'fpm_model_t' ) if ( allocated ( error )) return call get_value ( table , \"module-prefix\" , self % module_prefix % s ) end subroutine model_load_from_toml end module fpm_model","tags":"","loc":"sourcefile/fpm_model.f90.html"},{"title":"fpm_backend_console.f90 – Fortran-lang/fpm","text":"Source Code !># Build Backend Console !> This module provides a lightweight implementation for printing to the console !> and updating previously-printed console lines. It used by `[[fpm_backend_output]]` !> for pretty-printing build status and progress. !> !> @note The implementation for updating previous lines relies on no other output !> going to `stdout`/`stderr` except through the `console_t` object provided. !> !> @note All write statements to `stdout` are enclosed within OpenMP `critical` regions !> module fpm_backend_console use iso_fortran_env , only : stdout => output_unit implicit none private public :: console_t public :: LINE_RESET public :: COLOR_RED , COLOR_GREEN , COLOR_YELLOW , COLOR_RESET character ( len =* ), parameter :: ESC = char ( 27 ) !> Escape code for erasing current line character ( len =* ), parameter :: LINE_RESET = ESC // \"[2K\" // ESC // \"[1G\" !> Escape code for moving up one line character ( len =* ), parameter :: LINE_UP = ESC // \"[1A\" !> Escape code for moving down one line character ( len =* ), parameter :: LINE_DOWN = ESC // \"[1B\" !> Escape code for red foreground color character ( len =* ), parameter :: COLOR_RED = ESC // \"[31m\" !> Escape code for green foreground color character ( len =* ), parameter :: COLOR_GREEN = ESC // \"[32m\" !> Escape code for yellow foreground color character ( len =* ), parameter :: COLOR_YELLOW = ESC // \"[93m\" !> Escape code to reset foreground color character ( len =* ), parameter :: COLOR_RESET = ESC // \"[0m\" !> Console object type console_t !> Number of lines printed integer :: n_line = 1 contains !> Write a single line to the console procedure :: write_line => console_write_line !> Update a previously-written console line procedure :: update_line => console_update_line end type console_t contains !> Write a single line to the standard output subroutine console_write_line ( console , str , line , advance ) !> Console object class ( console_t ), intent ( inout ) :: console !> String to write character ( * ), intent ( in ) :: str !> Integer needed to later update console line integer , intent ( out ), optional :: line !> Advancing output (print newline?) logical , intent ( in ), optional :: advance character ( 3 ) :: adv adv = \"yes\" if ( present ( advance )) then if (. not . advance ) then adv = \"no\" end if end if !$omp critical if ( present ( line )) then line = console % n_line end if write ( stdout , '(A)' , advance = trim ( adv )) LINE_RESET // str if ( adv == \"yes\" ) then console % n_line = console % n_line + 1 end if !$omp end critical end subroutine console_write_line !> Overwrite a previously-written line in standard output subroutine console_update_line ( console , line_no , str ) !> Console object class ( console_t ), intent ( in ) :: console !> Integer output from `[[console_write_line]]` integer , intent ( in ) :: line_no !> New string to overwrite line character ( * ), intent ( in ) :: str integer :: n !$omp critical n = console % n_line - line_no ! Step back to line write ( stdout , '(A)' , advance = \"no\" ) repeat ( LINE_UP , n ) // LINE_RESET write ( stdout , '(A)' , advance = \"no\" ) str ! Step forward to end write ( stdout , '(A)' , advance = \"no\" ) repeat ( LINE_DOWN , n ) // LINE_RESET !$omp end critical end subroutine console_update_line end module fpm_backend_console","tags":"","loc":"sourcefile/fpm_backend_console.f90.html"},{"title":"fpm_os.F90 – Fortran-lang/fpm","text":"Source Code module fpm_os use , intrinsic :: iso_c_binding , only : c_char , c_int , c_null_char , c_ptr , c_associated use fpm_filesystem , only : exists , join_path , get_home use fpm_environment , only : os_is_unix use fpm_error , only : error_t , fatal_error implicit none private public :: change_directory , get_current_directory , get_absolute_path , convert_to_absolute_path , & & get_absolute_path_by_cd integer ( c_int ), parameter :: buffersize = 1000_c_int #ifndef _WIN32 character ( len =* ), parameter :: pwd_env = \"PWD\" #else character ( len =* ), parameter :: pwd_env = \"CD\" #endif interface function chdir_ ( path ) result ( stat ) & #ifndef _WIN32 bind ( C , name = \"chdir\" ) #else bind ( C , name = \"_chdir\" ) #endif import :: c_char , c_int character ( kind = c_char , len = 1 ), intent ( in ) :: path ( * ) integer ( c_int ) :: stat end function chdir_ function getcwd_ ( buf , bufsize ) result ( path ) & #ifndef _WIN32 bind ( C , name = \"getcwd\" ) #else bind ( C , name = \"_getcwd\" ) #endif import :: c_char , c_int , c_ptr character ( kind = c_char , len = 1 ), intent ( in ) :: buf ( * ) integer ( c_int ), value , intent ( in ) :: bufsize type ( c_ptr ) :: path end function getcwd_ !> Determine the absolute, canonicalized path for a given path. Unix-only. function realpath ( path , resolved_path ) result ( ptr ) bind ( C ) import :: c_ptr , c_char , c_int character ( kind = c_char , len = 1 ), intent ( in ) :: path ( * ) character ( kind = c_char , len = 1 ), intent ( out ) :: resolved_path ( * ) type ( c_ptr ) :: ptr end function realpath !> Determine the absolute, canonicalized path for a given path. Windows-only. function fullpath ( resolved_path , path , maxLength ) result ( ptr ) bind ( C , name = \"_fullpath\" ) import :: c_ptr , c_char , c_int character ( kind = c_char , len = 1 ), intent ( in ) :: path ( * ) character ( kind = c_char , len = 1 ), intent ( out ) :: resolved_path ( * ) integer ( c_int ), value , intent ( in ) :: maxLength type ( c_ptr ) :: ptr end function fullpath !> Determine the absolute, canonicalized path for a given path. !> Calls custom C routine because the `_WIN32` macro is correctly exported !> in C using `gfortran`. function c_realpath ( path , resolved_path , maxLength ) result ( ptr ) & bind ( C , name = \"c_realpath\" ) import :: c_ptr , c_char , c_int character ( kind = c_char , len = 1 ), intent ( in ) :: path ( * ) character ( kind = c_char , len = 1 ), intent ( out ) :: resolved_path ( * ) integer ( c_int ), value , intent ( in ) :: maxLength type ( c_ptr ) :: ptr end function c_realpath end interface contains subroutine change_directory ( path , error ) character ( len =* ), intent ( in ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: cpath (:) integer :: stat allocate ( cpath ( len ( path ) + 1 )) call f_c_character ( path , cpath , len ( path ) + 1 ) stat = chdir_ ( cpath ) if ( stat /= 0 ) then call fatal_error ( error , \"Failed to change directory to '\" // path // \"'\" ) end if end subroutine change_directory subroutine get_current_directory ( path , error ) character ( len = :), allocatable , intent ( out ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: cpath (:) type ( c_ptr ) :: tmp allocate ( cpath ( buffersize )) tmp = getcwd_ ( cpath , buffersize ) if ( c_associated ( tmp )) then call c_f_character ( cpath , path ) else call fatal_error ( error , \"Failed to retrieve current directory\" ) end if end subroutine get_current_directory subroutine f_c_character ( rhs , lhs , len ) character ( kind = c_char ), intent ( out ) :: lhs ( * ) character ( len =* ), intent ( in ) :: rhs integer , intent ( in ) :: len integer :: length length = min ( len - 1 , len_trim ( rhs )) lhs ( 1 : length ) = transfer ( rhs ( 1 : length ), lhs ( 1 : length )) lhs ( length + 1 : length + 1 ) = c_null_char end subroutine f_c_character subroutine c_f_character ( rhs , lhs ) character ( kind = c_char ), intent ( in ) :: rhs ( * ) character ( len = :), allocatable , intent ( out ) :: lhs integer :: ii do ii = 1 , huge ( ii ) - 1 if ( rhs ( ii ) == c_null_char ) then exit end if end do allocate ( character ( len = ii - 1 ) :: lhs ) lhs = transfer ( rhs ( 1 : ii - 1 ), lhs ) end subroutine c_f_character !> Determine the canonical, absolute path for the given path. !> !> Calls a C routine that uses the `_WIN32` macro to determine the correct function. !> !> Cannot be used in bootstrap mode. subroutine get_realpath ( path , real_path , error ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable , intent ( out ) :: real_path type ( error_t ), allocatable , intent ( out ) :: error character ( kind = c_char , len = 1 ), allocatable :: appended_path (:) character ( kind = c_char , len = 1 ), allocatable :: cpath (:) type ( c_ptr ) :: ptr if (. not . exists ( path )) then call fatal_error ( error , \"Cannot determine absolute path. Path '\" // path // \"' does not exist.\" ) return end if allocate ( appended_path ( len ( path ) + 1 )) call f_c_character ( path , appended_path , len ( path ) + 1 ) allocate ( cpath ( buffersize )) #ifndef FPM_BOOTSTRAP ptr = c_realpath ( appended_path , cpath , buffersize ) #endif if ( c_associated ( ptr )) then call c_f_character ( cpath , real_path ) else call fatal_error ( error , \"Failed to retrieve absolute path for '\" // path // \"'.\" ) end if end subroutine !> Determine the canonical, absolute path for the given path. !> Expands home folder (~) on both Unix and Windows. subroutine get_absolute_path ( path , absolute_path , error ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable , intent ( out ) :: absolute_path type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: home #ifdef FPM_BOOTSTRAP call get_absolute_path_by_cd ( path , absolute_path , error ); return #endif if ( len_trim ( path ) < 1 ) then call fatal_error ( error , 'Path cannot be empty' ); return else if ( path ( 1 : 1 ) == '~' ) then call get_home ( home , error ) if ( allocated ( error )) return if ( len_trim ( path ) == 1 ) then absolute_path = home ; return end if if ( os_is_unix ()) then if ( path ( 2 : 2 ) /= '/' ) then call fatal_error ( error , \"Wrong separator in path: '\" // path // \"'\" ); return end if else if ( path ( 2 : 2 ) /= '\\') then call fatal_error(error, \"Wrong separator in path: ' \"//path//\" '\"); return end if end if if (len_trim(path) == 2) then absolute_path = home; return end if absolute_path = join_path(home, path(3:len_trim(path))) if (.not. exists(absolute_path)) then call fatal_error(error, \"Path not found: ' \"//absolute_path//\" '\" ); return end if else ! Get canonicalized absolute path from either the absolute or the relative path. call get_realpath ( path , absolute_path , error ) end if end subroutine !> Alternative to `get_absolute_path` that uses `chdir`/`_chdir` to determine the absolute path. !> !> `get_absolute_path` is preferred but `get_absolute_path_by_cd` can be used in bootstrap mode. subroutine get_absolute_path_by_cd ( path , absolute_path , error ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable , intent ( out ) :: absolute_path type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: current_path call get_current_directory ( current_path , error ) if ( allocated ( error )) return call change_directory ( path , error ) if ( allocated ( error )) return call get_current_directory ( absolute_path , error ) if ( allocated ( error )) return call change_directory ( current_path , error ) if ( allocated ( error )) return end subroutine !> Converts a path to an absolute, canonical path. subroutine convert_to_absolute_path ( path , error ) character ( len = :), allocatable , intent ( inout ) :: path type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: absolute_path call get_absolute_path ( path , absolute_path , error ) path = absolute_path end subroutine end module fpm_os","tags":"","loc":"sourcefile/fpm_os.f90.html"},{"title":"meta.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the metapackage configuration data. !> !> A metapackage table can currently have the following fields !> !>```toml !>[metapackages] !>fpm = \"0.1.0\" !>openmp = bool !>stdlib = bool !>``` module fpm_manifest_metapackages use fpm_error , only : error_t , fatal_error , syntax_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value use fpm_environment implicit none private public :: metapackage_config_t , new_meta_config , is_meta_package public :: metapackage_request_t , new_meta_request !> Configuration data for a single metapackage request type :: metapackage_request_t !> Request flag logical :: on = . false . !> Metapackage name character ( len = :), allocatable :: name !> Version Specification string character ( len = :), allocatable :: version end type metapackage_request_t !> Configuration data for metapackages type :: metapackage_config_t !> Request MPI support type ( metapackage_request_t ) :: mpi !> Request OpenMP support type ( metapackage_request_t ) :: openmp !> Request stdlib support type ( metapackage_request_t ) :: stdlib !> fortran-lang minpack type ( metapackage_request_t ) :: minpack !> HDF5 type ( metapackage_request_t ) :: hdf5 end type metapackage_config_t contains !> Destroy a metapackage request elemental subroutine request_destroy ( self ) !> Instance of the request class ( metapackage_request_t ), intent ( inout ) :: self self % on = . false . if ( allocated ( self % version )) deallocate ( self % version ) if ( allocated ( self % name )) deallocate ( self % name ) end subroutine request_destroy !> Parse version string of a metapackage request subroutine request_parse ( self , version_request , error ) ! Instance of this metapackage type ( metapackage_request_t ), intent ( inout ) :: self ! Parse version request character ( len =* ), intent ( in ) :: version_request ! Error message type ( error_t ), allocatable , intent ( out ) :: error ! wildcard = use any versions if ( version_request == \"*\" ) then ! Any version is OK self % on = . true . self % version = version_request else call fatal_error ( error , 'Value <' // version_request // '> for metapackage ' // self % name // & 'is not currently supported. Try \"*\" instead. ' ) return end if end subroutine request_parse !> Construct a new metapackage request from the dependencies table subroutine new_meta_request ( self , key , table , meta_allowed , error ) type ( metapackage_request_t ), intent ( out ) :: self !> The package name character ( len =* ), intent ( in ) :: key !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys allowed to be metapackages logical , intent ( in ), optional :: meta_allowed (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat , i character ( len = :), allocatable :: value logical , allocatable :: allow_meta (:) type ( toml_key ), allocatable :: keys (:) call request_destroy ( self ) !> Set name self % name = key if (. not . is_meta_package ( key )) then call fatal_error ( error , \"Error reading fpm.toml: <\" // key // \"> is not a valid metapackage name\" ) return end if !> The toml table is not checked here because it already passed !> the \"new_dependencies\" check call table % get_keys ( keys ) !> Set list of entries that are allowed to be metapackages if ( present ( meta_allowed )) then if ( size ( meta_allowed ) /= size ( keys )) then call fatal_error ( error , \"Internal error: list of metapackage-enable entries does not match table size\" ) return end if allow_meta = meta_allowed else allocate ( allow_meta ( size ( keys )), source = . true .) endif do i = 1 , size ( keys ) ! Skip standard dependencies if (. not . allow_meta ( i )) cycle if ( keys ( i )% key == key ) then call get_value ( table , key , value ) if (. not . allocated ( value )) then call syntax_error ( error , \"Could not retrieve version string for metapackage key <\" // key // \">. Check syntax\" ) return else call request_parse ( self , value , error ) return endif end if end do ! Key is not present, metapackage not requested return end subroutine new_meta_request !> Construct a new build configuration from a TOML data structure subroutine new_meta_config ( self , table , meta_allowed , error ) !> Instance of the build configuration type ( metapackage_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> List of keys allowed to be metapackages logical , intent ( in ) :: meta_allowed (:) !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat !> The toml table is not checked here because it already passed !> the \"new_dependencies\" check call new_meta_request ( self % openmp , \"openmp\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % stdlib , \"stdlib\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % minpack , \"minpack\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % mpi , \"mpi\" , table , meta_allowed , error ) if ( allocated ( error )) return call new_meta_request ( self % hdf5 , \"hdf5\" , table , meta_allowed , error ) if ( allocated ( error )) return end subroutine new_meta_config !> Check local schema for allowed entries logical function is_meta_package ( key ) !> Instance of the TOML data structure character ( * ), intent ( in ) :: key select case ( key ) !> Supported metapackages case ( \"openmp\" , \"stdlib\" , \"mpi\" , \"minpack\" , \"hdf5\" ) is_meta_package = . true . case default is_meta_package = . false . end select end function is_meta_package end module fpm_manifest_metapackages","tags":"","loc":"sourcefile/meta.f90.html"},{"title":"publish.f90 – Fortran-lang/fpm","text":"Source Code !> Upload a package to the registry using the `publish` command. !> !> To upload a package you need to provide a token that will be linked to your username and created for a namespace. !> The token can be obtained from the registry website. It can be used as `fpm publish --token `. module fpm_cmd_publish use fpm_command_line , only : fpm_publish_settings use fpm_manifest , only : package_config_t , get_package_data use fpm_model , only : fpm_model_t use fpm_error , only : error_t , fpm_stop use fpm_versioning , only : version_t use fpm_filesystem , only : exists , join_path , get_temp_filename , delete_file use fpm_git , only : git_archive use fpm_downloader , only : downloader_t use fpm_strings , only : string_t use fpm_settings , only : official_registry_base_url use fpm , only : build_model implicit none private public :: cmd_publish contains !> The `publish` command first builds the root package to obtain all the relevant information such as the !> package version. It then creates a tarball of the package and uploads it to the registry. subroutine cmd_publish ( settings ) type ( fpm_publish_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( error_t ), allocatable :: error type ( version_t ), allocatable :: version type ( string_t ), allocatable :: upload_data (:) character ( len = :), allocatable :: tmp_file type ( downloader_t ) :: downloader integer :: i ! Get package data to determine package version. call get_package_data ( package , 'fpm.toml' , error , apply_defaults = . true .) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_build* Package error: ' // error % message ) version = package % version if ( settings % show_package_version ) then print * , version % s (); return end if !> Checks before uploading the package. if (. not . allocated ( package % license )) call fpm_stop ( 1 , 'No license specified in fpm.toml.' ) if (. not . package % build % module_naming ) call fpm_stop ( 1 , 'The package does not meet the module naming requirements. ' // & & 'Please set \"module-naming = true\" in fpm.toml [build] or specify a custom module prefix.' ) if (. not . allocated ( version )) call fpm_stop ( 1 , 'No version specified in fpm.toml.' ) if ( version % s () == '0' ) call fpm_stop ( 1 , 'Invalid version: \"' // version % s () // '\".' ) if (. not . exists ( 'fpm.toml' )) call fpm_stop ( 1 , \"Cannot find 'fpm.toml' file. Are you in the project root?\" ) ! Build model to obtain dependency tree. call build_model ( model , settings % fpm_build_settings , package , error ) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_build* Model error: ' // error % message ) ! Check if package contains git dependencies. Only publish packages without git dependencies. do i = 1 , model % deps % ndep if ( allocated ( model % deps % dep ( i )% git )) then call fpm_stop ( 1 , 'Do not publish packages containing git dependencies. ' // & & \"Please upload '\" // model % deps % dep ( i )% name // \"' to the registry first.\" ) end if end do tmp_file = get_temp_filename () call git_archive ( '.' , tmp_file , 'HEAD' , additional_files = [ 'fpm_model.json' ], verbose = settings % verbose , error = error ) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_publish* Archive error: ' // error % message ) call model % dump ( 'fpm_model.json' , error , json = . true .) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_publish* Model dump error: ' // error % message ) upload_data = [ & & string_t ( 'package_name=\"' // package % name // '\"' ), & & string_t ( 'package_license=\"' // package % license // '\"' ), & & string_t ( 'package_version=\"' // version % s () // '\"' ), & & string_t ( 'tarball=@\"' // tmp_file // '\"' ) & & ] if ( allocated ( settings % token )) upload_data = [ upload_data , string_t ( 'upload_token=\"' // settings % token // '\"' )] if ( settings % show_upload_data ) then call print_upload_data ( upload_data ); return end if ! Make sure a token is provided for publishing. if ( allocated ( settings % token )) then if ( settings % token == '' ) then call delete_file ( tmp_file ); call fpm_stop ( 1 , 'No token provided.' ) end if else call delete_file ( tmp_file ); call fpm_stop ( 1 , 'No token provided.' ) end if if ( settings % verbose ) then call print_upload_data ( upload_data ) print * , '' end if ! Perform network request and validate package, token etc. on the backend once ! https://github.com/fortran-lang/registry/issues/41 is resolved. if ( settings % is_dry_run ) then print * , 'Dry run successful. Generated tarball: ' , tmp_file ; return end if call downloader % upload_form ( official_registry_base_url // '/packages' , upload_data , settings % verbose , error ) call delete_file ( tmp_file ) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_publish* Upload error: ' // error % message ) end subroutine print_upload_data ( upload_data ) type ( string_t ), intent ( in ) :: upload_data (:) integer :: i print * , 'Upload data:' do i = 1 , size ( upload_data ) print * , upload_data ( i )% s end do end end","tags":"","loc":"sourcefile/publish.f90.html"},{"title":"example.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for an example. !> !> The example data structure is effectively a decorated version of an executable !> and shares most of its properties, except for the defaults and can be !> handled under most circumstances just like any other executable. !> !> A example table can currently have the following fields !> !>```toml !>[[ example ]] !>name = \"string\" !>source-dir = \"path\" !>main = \"file\" !>link = [\"lib\"] !>[example.dependencies] !>``` module fpm_manifest_example use fpm_manifest_dependency , only : dependency_config_t , new_dependencies use fpm_manifest_executable , only : executable_config_t use fpm_error , only : error_t , syntax_error , bad_name_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list implicit none private public :: example_config_t , new_example !> Configuation meta data for an example type , extends ( executable_config_t ) :: example_config_t contains !> Print information on this instance procedure :: info end type example_config_t contains !> Construct a new example configuration from a TOML data structure subroutine new_example ( self , table , error ) !> Instance of the example configuration type ( example_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve example name\" ) return end if if ( bad_name_error ( error , 'example' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"example\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_example !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) logical :: name_present integer :: ikey name_present = . false . call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Example section does not provide sufficient entries\" ) return end if do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in example entry\" ) exit case ( \"name\" ) name_present = . true . case ( \"source-dir\" , \"main\" , \"dependencies\" , \"link\" ) continue end select end do if ( allocated ( error )) return if (. not . name_present ) then call syntax_error ( error , \"Example name is not provided, please add a name entry\" ) end if end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the example configuration class ( example_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ii character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' , & & fmti = '(\"#\", 1x, a, t30, i0)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Example target\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % source_dir )) then if ( self % source_dir /= \"example\" . or . pr > 2 ) then write ( unit , fmt ) \"- source directory\" , self % source_dir end if end if if ( allocated ( self % main )) then if ( self % main /= \"main.f90\" . or . pr > 2 ) then write ( unit , fmt ) \"- example source\" , self % main end if end if if ( allocated ( self % dependency )) then if ( size ( self % dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- dependencies\" , size ( self % dependency ) end if do ii = 1 , size ( self % dependency ) call self % dependency ( ii )% info ( unit , pr - 1 ) end do end if end subroutine info end module fpm_manifest_example","tags":"","loc":"sourcefile/example.f90.html"},{"title":"fpm_source_parsing.f90 – Fortran-lang/fpm","text":"Source Code !># Parsing of package source files !> !> This module exposes two functions, `[[parse_f_source]]` and `[[parse_c_source]]`, !> which perform a rudimentary parsing of fortran and c source files !> in order to extract information required for module dependency tracking. !> !> Both functions additionally calculate and store a file digest (hash) which !> is used by the backend ([[fpm_backend]]) to skip compilation of unmodified sources. !> !> Both functions return an instance of the [[srcfile_t]] type. !> !> For more information, please read the documentation for each function: !> !> - `[[parse_f_source]]` !> - `[[parse_c_source]]` !> module fpm_source_parsing use fpm_error , only : error_t , file_parse_error , fatal_error , file_not_found_error use fpm_strings , only : string_t , string_cat , len_trim , split , lower , str_ends_with , fnv_1a , is_fortran_name use fpm_model , only : srcfile_t , & FPM_UNIT_UNKNOWN , FPM_UNIT_PROGRAM , FPM_UNIT_MODULE , & FPM_UNIT_SUBMODULE , FPM_UNIT_SUBPROGRAM , & FPM_UNIT_CSOURCE , FPM_UNIT_CHEADER , FPM_SCOPE_UNKNOWN , & FPM_SCOPE_LIB , FPM_SCOPE_DEP , FPM_SCOPE_APP , FPM_SCOPE_TEST , & FPM_UNIT_CPPSOURCE use fpm_filesystem , only : read_lines , read_lines_expanded , exists implicit none private public :: parse_f_source , parse_c_source , parse_use_statement contains !> Parsing of free-form fortran source files !> !> The following statements are recognised and parsed: !> !> - `Module`/`submodule`/`program` declaration !> - Module `use` statement !> - `include` statement !> !> @note Intrinsic modules used by sources are not listed in !> the `modules_used` field of source objects. !> !> @note Submodules are treated as normal modules which `use` their !> corresponding parent modules. !> !>### Parsing limitations !> !> __Statements must not continued onto another line !> except for an `only:` list in the `use` statement.__ !> !> This is supported: !> !>```fortran !> use my_module, only: & !> my_var, my_function, my_subroutine !>``` !> !> This is __NOT supported:__ !> !>```fortran !> use & !> my_module !>``` !> function parse_f_source ( f_filename , error ) result ( f_source ) character ( * ), intent ( in ) :: f_filename type ( srcfile_t ) :: f_source type ( error_t ), allocatable , intent ( out ) :: error logical :: inside_module , inside_interface , using , intrinsic_module integer :: stat integer :: fh , n_use , n_include , n_mod , n_parent , i , j , ic , pass type ( string_t ), allocatable :: file_lines (:), file_lines_lower (:) character (:), allocatable :: temp_string , mod_name , string_parts (:) if (. not . exists ( f_filename )) then call file_not_found_error ( error , f_filename ) return end if f_source % file_name = f_filename file_lines = read_lines_expanded ( f_filename ) ! for efficiency in parsing make a lowercase left-adjusted copy of the file ! Need a copy because INCLUDE (and #include) file arguments are case-sensitive file_lines_lower = file_lines do i = 1 , size ( file_lines_lower ) file_lines_lower ( i )% s = adjustl ( lower ( file_lines_lower ( i )% s )) enddo ! fnv_1a can only be applied to non-zero-length arrays if ( len_trim ( file_lines_lower ) > 0 ) f_source % digest = fnv_1a ( file_lines ) do pass = 1 , 2 n_use = 0 n_include = 0 n_mod = 0 n_parent = 0 inside_module = . false . inside_interface = . false . file_loop : do i = 1 , size ( file_lines_lower ) ! Skip comment lines and preprocessor directives if ( index ( file_lines_lower ( i )% s , '!' ) == 1 . or . & index ( file_lines_lower ( i )% s , '#' ) == 1 . or . & len_trim ( file_lines_lower ( i )% s ) < 1 ) then cycle end if ! Detect exported C-API via bind(C) if (. not . inside_interface . and . & parse_subsequence ( file_lines_lower ( i )% s , 'bind' , '(' , 'c' )) then do j = i , 1 , - 1 if ( index ( file_lines_lower ( j )% s , 'function' ) > 0 . or . & index ( file_lines_lower ( j )% s , 'subroutine' ) > 0 ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM exit end if if ( j > 1 ) then ic = index ( file_lines_lower ( j - 1 )% s , '!' ) if ( ic < 1 ) then ic = len ( file_lines_lower ( j - 1 )% s ) end if temp_string = trim ( file_lines_lower ( j - 1 )% s ( 1 : ic )) if ( index ( temp_string , '&' ) /= len ( temp_string )) then exit end if end if end do end if ! Skip lines that are continued: not statements if ( i > 1 ) then ic = index ( file_lines_lower ( i - 1 )% s , '!' ) if ( ic < 1 ) then ic = len ( file_lines_lower ( i - 1 )% s ) end if temp_string = trim ( file_lines_lower ( i - 1 )% s ( 1 : ic )) if ( len ( temp_string ) > 0 . and . index ( temp_string , '&' ) == len ( temp_string )) then cycle end if end if ! Detect beginning of interface block if ( index ( file_lines_lower ( i )% s , 'interface' ) == 1 & . or . parse_sequence ( file_lines_lower ( i )% s , 'abstract' , 'interface' )) then inside_interface = . true . cycle end if ! Detect end of interface block if ( parse_sequence ( file_lines_lower ( i )% s , 'end' , 'interface' )) then inside_interface = . false . cycle end if ! Process 'USE' statements call parse_use_statement ( f_filename , i , file_lines_lower ( i )% s , using , intrinsic_module , mod_name , error ) if ( allocated ( error )) return if ( using ) then ! Not a valid module name? if (. not . is_fortran_name ( mod_name )) cycle ! Valid intrinsic module: not a dependency if ( intrinsic_module ) cycle n_use = n_use + 1 if ( pass == 2 ) f_source % modules_used ( n_use )% s = mod_name cycle endif ! Process 'INCLUDE' statements ic = index ( file_lines_lower ( i )% s , 'include' ) if ( ic == 1 ) then ic = index ( lower ( file_lines ( i )% s ), 'include' ) if ( index ( adjustl ( file_lines ( i )% s ( ic + 7 :)), '\"' ) == 1 . or . & index ( adjustl ( file_lines ( i )% s ( ic + 7 :)), \"'\" ) == 1 ) then n_include = n_include + 1 if ( pass == 2 ) then f_source % include_dependencies ( n_include )% s = & & split_n ( file_lines ( i )% s , n = 2 , delims = \"'\" // '\"' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find include file name' , i , & file_lines ( i )% s ) return end if end if cycle end if end if ! Extract name of module if is module if ( index ( file_lines_lower ( i )% s , 'module ' ) == 1 ) then ! Remove any trailing comments ic = index ( file_lines_lower ( i )% s , '!' ) - 1 if ( ic < 1 ) then ic = len ( file_lines_lower ( i )% s ) end if temp_string = trim ( file_lines_lower ( i )% s ( 1 : ic )) ! R1405 module-stmt := \"MODULE\" module-name ! module-stmt has two space-delimited parts only ! (no line continuations) call split ( temp_string , string_parts , ' ' ) if ( size ( string_parts ) /= 2 ) then cycle end if mod_name = trim ( adjustl ( string_parts ( 2 ))) if ( scan ( mod_name , '=(&' ) > 0 ) then ! Ignore these cases: ! module & ! module =* ! module (i) cycle end if if (. not . is_fortran_name ( mod_name )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for module' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , mod_name )) return end if n_mod = n_mod + 1 if ( pass == 2 ) then f_source % modules_provided ( n_mod ) = string_t ( mod_name ) end if if ( f_source % unit_type == FPM_UNIT_UNKNOWN ) then f_source % unit_type = FPM_UNIT_MODULE end if if (. not . inside_module ) then inside_module = . true . else ! Must have missed an end module statement (can't assume a pure module) if ( f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if end if cycle end if ! Extract name of submodule if is submodule if ( index ( file_lines_lower ( i )% s , 'submodule' ) == 1 ) then mod_name = split_n ( file_lines_lower ( i )% s , n = 3 , delims = '()' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to get submodule name' , i , & file_lines_lower ( i )% s ) return end if if (. not . is_fortran_name ( mod_name )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for submodule' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , mod_name )) return end if n_mod = n_mod + 1 temp_string = split_n ( file_lines_lower ( i )% s , n = 2 , delims = '()' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to get submodule ancestry' , i , & file_lines_lower ( i )% s ) return end if if ( f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBMODULE end if n_use = n_use + 1 inside_module = . true . n_parent = n_parent + 1 if ( pass == 2 ) then if ( index ( temp_string , ':' ) > 0 ) then temp_string = temp_string ( index ( temp_string , ':' ) + 1 :) end if if (. not . is_fortran_name ( temp_string )) then call file_parse_error ( error , f_filename , & 'empty or invalid name for submodule parent' , i , & file_lines_lower ( i )% s , index ( file_lines_lower ( i )% s , temp_string )) return end if f_source % modules_used ( n_use )% s = temp_string f_source % parent_modules ( n_parent )% s = temp_string f_source % modules_provided ( n_mod )% s = mod_name end if cycle end if ! Detect if contains a program ! - no modules allowed after program def ! - program header may be missing (only \"end program\" statement present) if ( index ( file_lines_lower ( i )% s , 'program ' ) == 1 . or . & parse_sequence ( file_lines_lower ( i )% s , 'end' , 'program' )) then temp_string = split_n ( file_lines_lower ( i )% s , n = 2 , delims = ' ' , stat = stat ) if ( stat == 0 ) then if ( scan ( temp_string , '=(' ) > 0 ) then ! Ignore: ! program =* ! program (i) =* cycle end if end if f_source % unit_type = FPM_UNIT_PROGRAM cycle end if ! Parse end module statement ! (to check for code outside of modules) if ( parse_sequence ( file_lines_lower ( i )% s , 'end' , 'module' ) . or . & parse_sequence ( file_lines_lower ( i )% s , 'end' , 'submodule' )) then inside_module = . false . cycle end if ! Any statements not yet parsed are assumed to be other code statements if (. not . inside_module . and . f_source % unit_type /= FPM_UNIT_PROGRAM ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if end do file_loop ! If unable to parse end of module statement, then can't assume pure module ! (there could be non-module subprograms present) if ( inside_module . and . f_source % unit_type == FPM_UNIT_MODULE ) then f_source % unit_type = FPM_UNIT_SUBPROGRAM end if if ( pass == 1 ) then allocate ( f_source % modules_used ( n_use )) allocate ( f_source % include_dependencies ( n_include )) allocate ( f_source % modules_provided ( n_mod )) allocate ( f_source % parent_modules ( n_parent )) end if end do end function parse_f_source !> Parsing of c, cpp source files !> !> The following statements are recognised and parsed: !> !> - `#include` preprocessor statement !> function parse_c_source ( c_filename , error ) result ( c_source ) character ( * ), intent ( in ) :: c_filename type ( srcfile_t ) :: c_source type ( error_t ), allocatable , intent ( out ) :: error integer :: fh , n_include , i , pass , stat type ( string_t ), allocatable :: file_lines (:) c_source % file_name = c_filename if ( str_ends_with ( lower ( c_filename ), \".c\" )) then c_source % unit_type = FPM_UNIT_CSOURCE else if ( str_ends_with ( lower ( c_filename ), \".h\" )) then c_source % unit_type = FPM_UNIT_CHEADER else if ( str_ends_with ( lower ( c_filename ), \".cpp\" )) then c_source % unit_type = FPM_UNIT_CPPSOURCE end if allocate ( c_source % modules_used ( 0 )) allocate ( c_source % modules_provided ( 0 )) allocate ( c_source % parent_modules ( 0 )) file_lines = read_lines ( c_filename ) ! Ignore empty files, returned as FPM_UNIT_UNKNOWN if ( len_trim ( file_lines ) < 1 ) then c_source % unit_type = FPM_UNIT_UNKNOWN return end if c_source % digest = fnv_1a ( file_lines ) do pass = 1 , 2 n_include = 0 file_loop : do i = 1 , size ( file_lines ) ! Process 'INCLUDE' statements if ( index ( adjustl ( lower ( file_lines ( i )% s )), '#include' ) == 1 . and . & index ( file_lines ( i )% s , '\"' ) > 0 ) then n_include = n_include + 1 if ( pass == 2 ) then c_source % include_dependencies ( n_include )% s = & & split_n ( file_lines ( i )% s , n = 2 , delims = '\"' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , c_filename , & 'unable to get c include file' , i , & file_lines ( i )% s , index ( file_lines ( i )% s , '\"' )) return end if end if end if end do file_loop if ( pass == 1 ) then allocate ( c_source % include_dependencies ( n_include )) end if end do end function parse_c_source !> Split a string on one or more delimeters !> and return the nth substring if it exists !> !> n=0 will return the last item !> n=-1 will return the penultimate item etc. !> !> stat = 1 on return if the index !> is not found !> function split_n ( string , delims , n , stat ) result ( substring ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: delims integer , intent ( in ) :: n integer , intent ( out ) :: stat character (:), allocatable :: substring integer :: i character (:), allocatable :: string_parts (:) call split ( string , string_parts , delims ) if ( n < 1 ) then i = size ( string_parts ) + n if ( i < 1 ) then allocate ( character ( len = 0 ) :: substring ) ! ifort bus error otherwise stat = 1 return end if else i = n end if if ( i > size ( string_parts )) then allocate ( character ( len = 0 ) :: substring ) ! ifort bus error otherwise stat = 1 return end if substring = trim ( adjustl ( string_parts ( i ))) stat = 0 end function split_n !> Parse a subsequence of blank-separated tokens within a string !> (see parse_sequence) function parse_subsequence ( string , t1 , t2 , t3 , t4 ) result ( found ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: t1 character ( * ), intent ( in ), optional :: t2 , t3 , t4 logical :: found integer :: offset , i found = . false . offset = 1 do i = index ( string ( offset :), t1 ) if ( i == 0 ) return offset = offset + i - 1 found = parse_sequence ( string ( offset :), t1 , t2 , t3 , t4 ) if ( found ) return offset = offset + len ( t1 ) if ( offset > len ( string )) return end do end function parse_subsequence !> Helper utility to parse sequences of tokens !> that may be optionally separated by zero or more spaces function parse_sequence ( string , t1 , t2 , t3 , t4 ) result ( found ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: t1 character ( * ), intent ( in ), optional :: t2 , t3 , t4 logical :: found integer :: post , n , incr , pos , token_n logical :: match n = len ( string ) found = . false . pos = 1 do token_n = 1 , 4 do while ( pos <= n ) if ( string ( pos : pos ) /= ' ' ) then exit end if pos = pos + 1 end do select case ( token_n ) case ( 1 ) incr = len ( t1 ) if ( pos + incr - 1 > n ) return match = string ( pos : pos + incr - 1 ) == t1 case ( 2 ) if (. not . present ( t2 )) exit incr = len ( t2 ) if ( pos + incr - 1 > n ) return match = string ( pos : pos + incr - 1 ) == t2 case ( 3 ) if (. not . present ( t3 )) exit incr = len ( t3 ) if ( pos + incr - 1 > n ) return match = string ( pos : pos + incr - 1 ) == t3 case ( 4 ) if (. not . present ( t4 )) exit incr = len ( t4 ) if ( pos + incr - 1 > n ) return match = string ( pos : pos + incr - 1 ) == t4 case default exit end select if (. not . match ) then return end if pos = pos + incr end do found = . true . end function parse_sequence ! USE [, intrinsic] :: module_name [, only: only_list] ! USE [, non_intrinsic] :: module_name [, only: only_list] subroutine parse_use_statement ( f_filename , i , line , use_stmt , is_intrinsic , module_name , error ) !> Current file name and line number (for error messaging) character ( * ), intent ( in ) :: f_filename integer , intent ( in ) :: i !> The line being parsed. MUST BE preprocessed with trim(adjustl() character ( * ), intent ( in ) :: line !> Does this line contain a `use` statement? logical , intent ( out ) :: use_stmt !> Is the module in this statement intrinsic? logical , intent ( out ) :: is_intrinsic !> used module name character (:), allocatable , intent ( out ) :: module_name !> Error handling type ( error_t ), allocatable , intent ( out ) :: error character ( 15 ), parameter :: INTRINSIC_NAMES ( * ) = & [ 'iso_c_binding ' , & 'iso_fortran_env' , & 'ieee_arithmetic' , & 'ieee_exceptions' , & 'ieee_features ' , & 'omp_lib ' ] character ( len = :), allocatable :: temp_string integer :: colons , intr , nonintr , j , stat logical :: has_intrinsic_name use_stmt = . false . is_intrinsic = . false . if ( len_trim ( line ) <= 0 ) return ! Quick check that the line is preprocessed if ( line ( 1 : 1 ) == ' ' ) then call fatal_error ( error , 'internal_error: source file line is not trim(adjustl()) on input to parse_use_statement' ) return end if ! 'use' should be the first string in the adjustl line use_stmt = index ( line , 'use ' ) == 1 . or . index ( line , 'use::' ) == 1 . or . index ( line , 'use,' ) == 1 if (. not . use_stmt ) return colons = index ( line , '::' ) nonintr = 0 intr = 0 have_colons : if ( colons > 3 ) then ! there may be an intrinsic/non-intrinsic spec nonintr = index ( line ( 1 : colons - 1 ), 'non_intrinsic' ) if ( nonintr == 0 ) intr = index ( line ( 1 : colons - 1 ), 'intrinsic' ) temp_string = split_n ( line , delims = ':' , n = 2 , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line , colons ) return end if module_name = split_n ( temp_string , delims = ' ,' , n = 1 , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line ) return end if else module_name = split_n ( line , n = 2 , delims = ' ,' , stat = stat ) if ( stat /= 0 ) then call file_parse_error ( error , f_filename , & 'unable to find used module name' , i , & line ) return end if end if have_colons ! If declared intrinsic, check that it is true has_intrinsic_name = any ([( index ( module_name , trim ( INTRINSIC_NAMES ( j ))) > 0 , & j = 1 , size ( INTRINSIC_NAMES ))]) if ( intr > 0 . and . . not . has_intrinsic_name ) then ! An intrinsic module was not found. Its name could be in the next line, ! in which case, we just skip this check. The compiler will do the job if the name is invalid. ! Module name was not read: it's in the next line if ( index ( module_name , '&' ) <= 0 ) then call file_parse_error ( error , f_filename , & 'module ' // module_name // ' is declared intrinsic but it is not ' , i , & line ) return endif endif ! Should we treat this as an intrinsic module is_intrinsic = nonintr == 0 . and . & ! not declared non-intrinsic ( intr > 0 . or . has_intrinsic_name ) end subroutine parse_use_statement end module fpm_source_parsing","tags":"","loc":"sourcefile/fpm_source_parsing.f90.html"},{"title":"executable.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for an executables. !> !> An executable table can currently have the following fields !> !>```toml !>[[ executable ]] !>name = \"string\" !>source-dir = \"path\" !>main = \"file\" !>link = [\"lib\"] !>[executable.dependencies] !>``` module fpm_manifest_executable use fpm_manifest_dependency , only : dependency_config_t , new_dependencies , resize use fpm_error , only : error_t , syntax_error , bad_name_error , fatal_error use fpm_strings , only : string_t , operator ( == ) use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list , serializable_t , add_table , & set_string , set_list implicit none private public :: executable_config_t , new_executable !> Configuation meta data for an executable type , extends ( serializable_t ) :: executable_config_t !> Name of the resulting executable character ( len = :), allocatable :: name !> Source directory for collecting the executable character ( len = :), allocatable :: source_dir !> Name of the source file declaring the main program character ( len = :), allocatable :: main !> Dependency meta data for this executable type ( dependency_config_t ), allocatable :: dependency (:) !> Libraries to link against type ( string_t ), allocatable :: link (:) contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => exe_is_same procedure :: dump_to_toml procedure :: load_from_toml end type executable_config_t character ( * ), parameter , private :: class_name = 'executable_config_t' contains !> Construct a new executable configuration from a TOML data structure subroutine new_executable ( self , table , error ) !> Instance of the executable configuration type ( executable_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve executable name\" ) return end if if ( bad_name_error ( error , 'executable' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"app\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_executable !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) logical :: name_present integer :: ikey name_present = . false . call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Executable section does not provide sufficient entries\" ) return end if do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed as executable entry\" ) exit case ( \"name\" ) name_present = . true . case ( \"source-dir\" , \"main\" , \"dependencies\" , \"link\" ) continue end select end do if ( allocated ( error )) return if (. not . name_present ) then call syntax_error ( error , \"Executable name is not provided, please add a name entry\" ) end if end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the executable configuration class ( executable_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ii character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' , & & fmti = '(\"#\", 1x, a, t30, i0)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Executable target\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % source_dir )) then if ( self % source_dir /= \"app\" . or . pr > 2 ) then write ( unit , fmt ) \"- source directory\" , self % source_dir end if end if if ( allocated ( self % main )) then if ( self % main /= \"main.f90\" . or . pr > 2 ) then write ( unit , fmt ) \"- program source\" , self % main end if end if if ( allocated ( self % dependency )) then if ( size ( self % dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- dependencies\" , size ( self % dependency ) end if do ii = 1 , size ( self % dependency ) call self % dependency ( ii )% info ( unit , pr - 1 ) end do end if end subroutine info logical function exe_is_same ( this , that ) class ( executable_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that integer :: ii exe_is_same = . false . select type ( other => that ) type is ( executable_config_t ) if (. not . this % link == other % link ) return if (. not . allocated ( this % name ). eqv . allocated ( other % name )) return if (. not . this % name == other % name ) return if (. not . allocated ( this % source_dir ). eqv . allocated ( other % source_dir )) return if (. not . this % source_dir == other % source_dir ) return if (. not . allocated ( this % main ). eqv . allocated ( other % main )) return if (. not . this % main == other % main ) return if (. not . allocated ( this % dependency ). eqv . allocated ( other % dependency )) return if ( allocated ( this % dependency )) then if (. not .( size ( this % dependency ) == size ( other % dependency ))) return do ii = 1 , size ( this % dependency ) if (. not .( this % dependency ( ii ) == other % dependency ( ii ))) return end do end if class default ! Not the same type return end select !> All checks passed! exe_is_same = . true . end function exe_is_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( executable_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables integer :: ierr , ii type ( toml_table ), pointer :: ptr_deps , ptr character ( 27 ) :: unnamed call set_string ( table , \"name\" , self % name , error ) if ( allocated ( error )) return call set_string ( table , \"source-dir\" , self % source_dir , error ) if ( allocated ( error )) return call set_string ( table , \"main\" , self % main , error ) if ( allocated ( error )) return if ( allocated ( self % dependency )) then ! Create dependency table call add_table ( table , \"dependencies\" , ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , class_name // \" cannot create dependency table \" ) return end if do ii = 1 , size ( self % dependency ) associate ( dep => self % dependency ( ii )) !> Because dependencies are named, fallback if this has no name !> So, serialization will work regardless of size(self%dep) == self%ndep if ( len_trim ( dep % name ) == 0 ) then write ( unnamed , 1 ) ii call add_table ( ptr_deps , trim ( unnamed ), ptr ) else call add_table ( ptr_deps , dep % name , ptr ) end if if (. not . associated ( ptr )) then call fatal_error ( error , class_name // \" cannot create entry for dependency \" // dep % name ) return end if call dep % dump_to_toml ( ptr , error ) if ( allocated ( error )) return end associate end do endif call set_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return 1 format ( 'UNNAMED_DEPENDENCY_' , i0 ) end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( executable_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Local variables type ( toml_key ), allocatable :: keys (:), dep_keys (:) type ( toml_table ), pointer :: ptr_deps , ptr integer :: ii , jj , ierr call table % get_keys ( keys ) call get_value ( table , \"name\" , self % name ) if ( allocated ( error )) return call get_value ( table , \"source-dir\" , self % source_dir ) if ( allocated ( error )) return call get_value ( table , \"main\" , self % main ) if ( allocated ( error )) return call get_list ( table , \"link\" , self % link , error ) find_deps_table : do ii = 1 , size ( keys ) if ( keys ( ii )% key == \"dependencies\" ) then call get_value ( table , keys ( ii ), ptr_deps ) if (. not . associated ( ptr_deps )) then call fatal_error ( error , class_name // ': error retrieving dependency table from TOML table' ) return end if !> Read all dependencies call ptr_deps % get_keys ( dep_keys ) call resize ( self % dependency , size ( dep_keys )) do jj = 1 , size ( dep_keys ) call get_value ( ptr_deps , dep_keys ( jj ), ptr ) call self % dependency ( jj )% load_from_toml ( ptr , error ) if ( allocated ( error )) return end do exit find_deps_table endif end do find_deps_table end subroutine load_from_toml end module fpm_manifest_executable","tags":"","loc":"sourcefile/executable.f90.html"},{"title":"new.f90 – Fortran-lang/fpm","text":"Source Code module fpm_cmd_new !># Definition of the \"new\" subcommand !> !> A type of the general command base class [[fpm_cmd_settings]] !> was created for the \"new\" subcommand ==> type [[fpm_new_settings]]. !> This procedure read the values that were set on the command line !> from this type to decide what actions to take. !> !> It is virtually self-contained and so independant of the rest of the !> application that it could function as a separate program. !> !> The \"new\" subcommand options currently consist of a SINGLE top !> directory name to create that must have a name that is an !> allowable Fortran variable name. That should have been ensured !> by the command line processing before this procedure is called. !> So basically this routine has already had the options vetted and !> just needs to conditionally create a few files. !> !> As described in the documentation it will selectively !> create the subdirectories app/, test/, src/, and example/ !> and populate them with sample files. !> !> It also needs to create an initial manifest file \"fpm.toml\". !> !> It then calls the system command \"git init\". !> !> It should test for file existence and not overwrite existing !> files and inform the user if there were conflicts. !> !> Any changes should be reflected in the documentation in !> [[fpm_command_line.f90]] !> !> FUTURE !> A filename like \".\" would need system commands or a standard routine !> like realpath(3c) to process properly. !> !> Perhaps allow more than one name on a single command. It is an arbitrary !> restriction based on a concensus preference, not a required limitation. !> !> Initially the name of the directory is used as the module name in the !> src file so it must be an allowable Fortran variable name. If there are !> complaints about it it might be changed. Handling unicode at this point !> might be problematic as not all current compilers handle it. Other !> utilities like content trackers (ie. git) or repositories like github !> might also have issues with alternative names or names with spaces, etc. !> So for the time being it seems prudent to encourage simple ASCII top directory !> names (similiar to the primary programming language Fortran itself). !> !> Should be able to create or pull more complicated initial examples !> based on various templates. It should place or mention other relevant !> documents such as a description of the manifest file format in user hands; !> or how to access registered packages and local packages, !> although some other command might provide that (and the help command should !> be the first go-to for a CLI utility). use fpm_command_line , only : fpm_new_settings use fpm_environment , only : OS_LINUX , OS_MACOS , OS_WINDOWS use fpm_filesystem , only : join_path , exists , basename , mkdir , is_dir use fpm_filesystem , only : fileopen , fileclose , warnwrite , which , run use fpm_strings , only : join , to_fortran_name use fpm_error , only : fpm_stop use , intrinsic :: iso_fortran_env , only : stderr => error_unit implicit none private public :: cmd_new contains subroutine cmd_new ( settings ) type ( fpm_new_settings ), intent ( in ) :: settings integer , parameter :: tfc = selected_char_kind ( 'DEFAULT' ) character ( len = :, kind = tfc ), allocatable :: bname ! baeename of NAME character ( len = :, kind = tfc ), allocatable :: tomlfile (:) character ( len = :, kind = tfc ), allocatable :: littlefile (:) !> TOP DIRECTORY NAME PROCESSING !> see if requested new directory already exists and process appropriately if ( exists ( settings % name ) . and . . not . settings % backfill ) then write ( stderr , '(*(g0,1x))' )& & '' , settings % name , 'already exists.' write ( stderr , '(*(g0,1x))' )& & ' perhaps you wanted to add --backfill ?' return elseif ( is_dir ( settings % name ) . and . settings % backfill ) then write ( * , '(*(g0))' ) 'backfilling ' , settings % name elseif ( exists ( settings % name ) ) then write ( stderr , '(*(g0,1x))' )& & '' , settings % name , 'already exists and is not a directory.' return else ! make new directory call mkdir ( settings % name ) endif !> temporarily change to new directory as a test. NB: System dependent call run ( 'cd ' // settings % name ) ! NOTE: need some system routines to handle filenames like \".\" ! like realpath() or getcwd(). bname = basename ( settings % name ) littlefile = [ character ( len = 80 ) :: '# ' // bname , 'My cool new project!' ] ! create NAME/README.md call warnwrite ( join_path ( settings % name , 'README.md' ), littlefile ) ! start building NAME/fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: & & ' # This is your fpm(Fortran Package Manager) manifest file ' ,& & ' # (\"fpm.toml\"). It is heavily annotated to help guide you though ' ,& & ' # customizing a package build, although the defaults are sufficient ' ,& & ' # for many basic packages. ' ,& & ' # ' ,& & ' # The manifest file is not only used to provide metadata identifying ' ,& & ' # your project (so it can be used by others as a dependency). It can ' ,& & ' # specify where your library and program sources live, what the name ' ,& & ' # of the executable(s) will be, what files to build, dependencies on ' ,& & ' # other fpm packages, and what external libraries are required. ' ,& & ' # ' ,& & ' # The manifest format must conform to the TOML configuration file ' ,& & ' # standard. ' ,& & ' # ' ,& & ' # TOML files support flexible use of white-space and commenting of the ' ,& & ' # configuration data, but for clarity in this sample active directives ' ,& & ' # begin in column one. Inactive example directives are commented ' ,& & ' # out with a pound character (\"#\") but begin in column one as well. ' ,& & ' # Commentary begins with a pound character in column three. ' ,& & ' # ' ,& & ' # This file draws heavily upon the following references: ' ,& & ' # ' ,& & ' # The fpm home page at ' ,& & ' # https://github.com/fortran-lang/fpm ' ,& & ' # A complete list of keys and their attributes at ' ,& & ' # https://github.com/fortran-lang/fpm/blob/main/manifest-reference.md ' ,& & ' # examples of fpm project packaging at ' ,& & ' # https://github.com/fortran-lang/fpm/blob/main/PACKAGING.md ' ,& & ' # The Fortran TOML file interface and it''s references at ' ,& & ' # https://github.com/toml-f/toml-f ' ,& & ' # ' ,& & ' #----------------------- ' ,& & ' # project Identification ' ,& & ' #----------------------- ' ,& & ' # We begin with project metadata at the manifest root. This data is designed ' ,& & ' # to aid others when searching for the project in a repository and to ' ,& & ' # identify how and when to contact the package supporters. ' ,& & ' ' ,& & 'name = \"' // bname // '\"' ,& & ' # The project name (required) is how the project will be referred to. ' ,& & ' # The name is used by other packages using it as a dependency. It also ' ,& & ' # is used as the default name of any library built and the optional ' ,& & ' # default executable built from app/main.f90. It must conform to the rules ' ,& & ' # for a Fortran variable name. ' ,& & ' ' ,& & 'version = \"0.1.0\" ' ,& & ' # The project version number is a string. A recommended scheme for ' ,& & ' # specifying versions is the Semantic Versioning scheme. ' ,& & ' ' ,& & 'license = \"license\" ' ,& & ' # Licensing information specified using SPDX identifiers is preferred ' ,& & ' # (eg. \"Apache-2.0 OR MIT\" or \"LGPL-3.0-or-later\"). ' ,& & ' ' ,& & 'maintainer = \"jane.doe@example.com\" ' ,& & ' # Information on the project maintainer and means to reach out to them. ' ,& & ' ' ,& & 'author = \"Jane Doe\" ' ,& & ' # Information on the project author. ' ,& & ' ' ,& & 'copyright = \"Copyright 2020 Jane Doe\" ' ,& & ' # A statement clarifying the Copyright status of the project. ' ,& & ' ' ,& & '#description = \"A short project summary in plain text\" ' ,& & ' # The description provides a short summary on the project. It should be ' ,& & ' # plain text and not use any markup formatting. ' ,& & ' ' ,& & '#categories = [\"fortran\", \"graphics\"] ' ,& & ' # Categories associated with the project. Listing only one is preferred. ' ,& & ' ' ,& & '#keywords = [\"hdf5\", \"mpi\"] ' ,& & ' # The keywords field is an array of strings describing the project. ' ,& & ' ' ,& & '#homepage = \"https://stdlib.fortran-lang.org\" ' ,& & ' # URL to the webpage of the project. ' ,& & ' ' ,& & ' # ----------------------------------------- ' ,& & ' # We are done with identifying the project. ' ,& & ' # ----------------------------------------- ' ,& & ' # ' ,& & ' # Now lets start describing how the project should be built. ' ,& & ' # ' ,& & ' # Note tables would go here but we will not be talking about them (much)!!' ,& & ' # ' ,& & ' # Tables are a way to explicitly specify large numbers of programs in ' ,& & ' # a compact format instead of individual per-program entries in the ' ,& & ' # [[executable]], [[test]], and [[example]] sections to follow but ' ,& & ' # will not be discussed further except for the following notes: ' ,& & ' # ' ,& & ' # + Tables must appear (here) before any sections are declared. Once a ' ,& & ' # section is specified in a TOML file everything afterwards must be ' ,& & ' # values for that section or the beginning of a new section. A simple ' ,& & ' # example looks like: ' ,& & ' ' ,& & '#executable = [ ' ,& & '# { name = \"a-prog\" }, ' ,& & '# { name = \"app-tool\", source-dir = \"tool\" }, ' ,& & '# { name = \"fpm-man\", source-dir = \"tool\", main=\"fman.f90\" } ' ,& & '#] ' ,& & ' ' ,& & ' # This would be in lieue of the [[executable]] section found later in this ' ,& & ' # configuration file. ' ,& & ' # + See the reference documents (at the beginning of this document) ' ,& & ' # for more information on tables if you have long lists of programs ' ,& & ' # to build and are not simply depending on auto-detection. ' ,& & ' # ' ,& & ' # Now lets begin the TOML sections (lines beginning with \"[\") ... ' ,& & ' # ' ,& & ' ' ,& & '[install] # Options for the \"install\" subcommand ' ,& & ' ' ,& & ' # When you run the \"install\" subcommand only executables are installed by ' ,& & ' # default on the local system. Library projects that will be used outside of ' ,& & ' # \"fpm\" can set the \"library\" boolean to also allow installing the module ' ,& & ' # files and library archive. Without this being set to \"true\" an \"install\" ' ,& & ' # subcommand ignores parameters that specify library installation. ' ,& & ' ' ,& & 'library = false ' ,& & ' ' ,& & '[build] # General Build Options ' ,& & ' ' ,& & ' ### Automatic target discovery ' ,& & ' # ' ,& & ' # Normally fpm recursively searches the app/, example/, and test/ directories ' ,& & ' # for program sources and builds them. To disable this automatic discovery of ' ,& & ' # program targets set the following to \"false\": ' ,& & ' ' ,& & '#auto-executables = true ' ,& & '#auto-examples = true ' ,& & '#auto-tests = true ' ,& & ' ' ,& & ' ### Package-level External Library Links ' ,& & ' # ' ,& & ' # To declare link-time dependencies on external libraries a list of ' ,& & ' # native libraries can be specified with the \"link\" entry. You may ' ,& & ' # have one library name or a list of strings in case several ' ,& & ' # libraries should be linked. This list of library dependencies is ' ,& & ' # exported to dependent packages. You may have to alter your library ' ,& & ' # search-path to ensure the libraries can be accessed. Typically, ' ,& & ' # this is done with the LD_LIBRARY_PATH environment variable on ULS ' ,& & ' # (Unix-Like Systems). You only specify the core name of the library ' ,& & ' # (as is typical with most programming environments, where you ' ,& & ' # would specify \"-lz\" on your load command to link against the zlib ' ,& & ' # compression library even though the library file would typically be ' ,& & ' # a file called \"libz.a\" \"or libz.so\"). So to link against that library ' ,& & ' # you would specify: ' ,& & ' ' ,& & '#link = \"z\" ' ,& & ' ' ,& & ' # Note that in some cases the order of the libraries matters: ' ,& & ' ' ,& & '#link = [\"blas\", \"lapack\"] ' ,& & '' ] endif if ( settings % with_bare ) then elseif ( settings % with_lib ) then call mkdir ( join_path ( settings % name , 'src' ) ) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & '[library] ' ,& & ' ' ,& & ' # You can change the name of the directory to search for your library ' ,& & ' # source from the default of \"src/\". Library targets are exported ' ,& & ' # and usable by other projects. ' ,& & ' ' ,& & 'source-dir=\"src\" ' ,& & ' ' ,& & ' # this can be a list: ' ,& & ' ' ,& & '#source-dir=[\"src\", \"src2\"] ' ,& & ' ' ,& & ' # More complex libraries may organize their modules in subdirectories. ' ,& & ' # For modules in a top-level directory fpm requires (but does not ' ,& & ' # enforce) that: ' ,& & ' # ' ,& & ' # + The module has the same name as the source file. This is important. ' ,& & ' # + There should be only one module per file. ' ,& & ' # ' ,& & ' # These two requirements simplify the build process for fpm. As Fortran ' ,& & ' # compilers emit module files (.mod) with the same name as the module ' ,& & ' # itself (but not the source file, .f90), naming the module the same ' ,& & ' # as the source file allows fpm to: ' ,& & ' # ' ,& & ' # + Uniquely and exactly map a source file (.f90) to its object (.o) ' ,& & ' # and module (.mod) files. ' ,& & ' # + Avoid conflicts with modules of the same name that could appear ' ,& & ' # in dependency packages. ' ,& & ' # ' ,& & ' ### Multi-level library source ' ,& & ' # You can place your module source files in any number of levels of ' ,& & ' # subdirectories inside your source directory, but there are certain naming ' ,& & ' # conventions to be followed -- module names must contain the path components ' ,& & ' # of the directory that its source file is in. ' ,& & ' # ' ,& & ' # This rule applies generally to any number of nested directories and ' ,& & ' # modules. For example, src/a/b/c/d.f90 must define a module called a_b_c_d. ' ,& & ' # Again, this is not enforced but may be required in future releases. ' ,& & '' ] endif ! create placeholder module src/bname.f90 littlefile = [ character ( len = 80 ) :: & & 'module ' // to_fortran_name ( bname ), & & ' implicit none' , & & ' private' , & & '' , & & ' public :: say_hello' , & & 'contains' , & & ' subroutine say_hello' , & & ' print *, \"Hello, ' // bname // '!\"' , & & ' end subroutine say_hello' , & & 'end module ' // to_fortran_name ( bname )] ! create NAME/src/NAME.f90 call warnwrite ( join_path ( settings % name , 'src' , bname // '.f90' ),& & littlefile ) endif if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile ,& & '[dependencies] ' ,& & ' ' ,& & ' # Inevitably, you will want to be able to include other packages in ' ,& & ' # a project. Fpm makes this incredibly simple, by taking care of ' ,& & ' # fetching and compiling your dependencies for you. You just tell it ' ,& & ' # what your dependencies names are, and where to find them. ' ,& & ' # ' ,& & ' # If you are going to distribute your package only place dependencies ' ,& & ' # here someone using your package as a remote dependency needs built. ' ,& & ' # You can define dependencies just for developer executables in the ' ,& & ' # next section, or even for specific executables as we will see below ' ,& & ' # (Then fpm will still fetch and compile it when building your ' ,& & ' # developer executables, but users of your library will not have to). ' ,& & ' # ' ,& & ' ## GLOBAL DEPENDENCIES (exported with your project) ' ,& & ' # ' ,& & ' # Typically, dependencies are defined by specifying the project''s ' ,& & ' # git repository. ' ,& & ' # ' ,& & ' # You can be specific about which version of a dependency you would ' ,& & ' # like. By default the latest default branch is used. You can ' ,& & ' # optionally specify a branch, a tag or a commit value. ' ,& & ' # ' ,& & ' # So here are several alternates for specifying a remote dependency (you ' ,& & ' # can have at most one of \"branch\", \"rev\" or \"tag\" present): ' ,& & ' ' ,& & '#stdlib = { git = \"https://github.com/LKedward/stdlib-fpm.git\" } ' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\",branch = \"master\" },' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\", tag = \"v0.1.0\" }, ' ,& & '#stdlib = {git=\"https://github.com/LKedward/stdlib-fpm.git\", rev = \"5a9b7a8\" }. ' ,& & ' ' ,& & ' # There may be multiple packages listed: ' ,& & ' ' ,& & '#M_strings = { git = \"https://github.com/urbanjost/M_strings.git\" } ' ,& & '#M_time = { git = \"https://github.com/urbanjost/M_time.git\" } ' ,& & ' ' ,& & ' # ' ,& & ' # You can even specify the local path to another project if it is in ' ,& & ' # a sub-folder (If for example you have got another fpm package **in ' ,& & ' # the same repository**) like this: ' ,& & ' ' ,& & '#M_strings = { path = \"M_strings\" } ' ,& & ' ' ,& & ' # This tells fpm that we depend on a crate called M_strings which is found ' ,& & ' # in the M_strings folder (relative to the fpm.toml it’s written in). ' ,& & ' # ' ,& & ' # For a more verbose layout use normal tables rather than inline tables ' ,& & ' # to specify dependencies: ' ,& & ' ' ,& & '#[dependencies.toml-f] ' ,& & '#git = \"https://github.com/toml-f/toml-f\" ' ,& & '#rev = \"2f5eaba864ff630ba0c3791126a3f811b6e437f3\" ' ,& & ' ' ,& & ' # Now you can use any modules from these libraries anywhere in your ' ,& & ' # code -- whether is in your library source or a program source. ' ,& & ' ' ,& & '[dev-dependencies] ' ,& & ' ' ,& & ' ## Dependencies Only for Development ' ,& & ' # ' ,& & ' # You can specify dependencies your library or application does not ' ,& & ' # depend on in a similar way. The difference is that these will not ' ,& & ' # be exported as part of your project to those using it as a remote ' ,& & ' # dependency. ' ,& & ' # ' ,& & ' # Currently, like a global dependency it will still be available for ' ,& & ' # all codes. It is up to the developer to ensure that nothing except ' ,& & ' # developer test programs rely upon it. ' ,& & ' ' ,& & '#M_msg = { git = \"https://github.com/urbanjost/M_msg.git\" } ' ,& & '#M_verify = { git = \"https://github.com/urbanjost/M_verify.git\" } ' ,& & '' ] endif if ( settings % with_bare ) then elseif ( settings % with_executable ) then ! create next section of fpm.toml call mkdir ( join_path ( settings % name , 'app' )) ! create NAME/app or stop if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & ' #----------------------------------- ' ,& & ' ## Application-specific declarations ' ,& & ' #----------------------------------- ' ,& & ' # Now lets begin entries for the TOML tables (lines beginning with \"[[\") ' ,& & ' # that describe the program sources -- applications, tests, and examples. ' ,& & ' # ' ,& & ' # First we will configuration individual applications run with \"fpm run\". ' ,& & ' # ' ,& & ' # + the \"name\" entry for the executable to be built must always ' ,& & ' # be specified. The name must satisfy the rules for a Fortran ' ,& & ' # variable name. This will be the name of the binary installed by ' ,& & ' # the \"install\" subcommand and used on the \"run\" subcommand. ' ,& & ' # + The source directory for each executable can be adjusted by the ' ,& & ' # \"source-dir\" entry. ' ,& & ' # + The basename of the source file containing the program body can ' ,& & ' # be specified with the \"main\" entry. ' ,& & ' # + Executables can also specify their own external package and ' ,& & ' # library link dependencies. ' ,& & ' # ' ,& & ' # Currently, like a global dependency any external package dependency ' ,& & ' # will be available for all codes. It is up to the developer to ensure ' ,& & ' # that nothing except the application programs specified rely upon it. ' ,& & ' # ' ,& & ' # Note if your application needs to use a module internally, but you do not ' ,& & ' # intend to build it as a library to be used in other projects, you can ' ,& & ' # include the module in your program source file or directory as well. ' ,& & ' ' ,& & '[[executable]] ' ,& & 'name=\"' // bname // '\"' ,& & 'source-dir=\"app\" ' ,& & 'main=\"main.f90\" ' ,& & ' ' ,& & ' # You may repeat this pattern to define additional applications. For instance,' ,& & ' # the following sample illustrates all accepted options, where \"link\" and ' ,& & ' # \"executable.dependencies\" keys are the same as the global external library ' ,& & ' # links and package dependencies described previously except they apply ' ,& & ' # only to this executable: ' ,& & ' ' ,& & '#[[ executable ]] ' ,& & '#name = \"app-name\" ' ,& & '#source-dir = \"prog\" ' ,& & '#main = \"program.f90\" ' ,& & '#link = \"z\" ' ,& & '#[executable.dependencies] ' ,& & '#M_CLI = { git = \"https://github.com/urbanjost/M_CLI.git\" } ' ,& & '#helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } ' ,& & '#M_path = { git = \"https://github.com/urbanjost/M_path.git\" } ' ,& & '' ] endif if ( exists ( bname // '/src/' )) then littlefile = [ character ( len = 80 ) :: & & 'program main' , & & ' use ' // to_fortran_name ( bname ) // ', only: say_hello' , & & ' implicit none' , & & '' , & & ' call say_hello()' , & & 'end program main' ] else littlefile = [ character ( len = 80 ) :: & & 'program main' , & & ' implicit none' , & & '' , & & ' print *, \"hello from project ' // bname // '\"' , & & 'end program main' ] endif call warnwrite ( join_path ( settings % name , 'app/main.f90' ), littlefile ) endif if ( settings % with_bare ) then elseif ( settings % with_test ) then ! create NAME/test or stop call mkdir ( join_path ( settings % name , 'test' )) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile ,& & '[[test]] ' ,& & ' ' ,& & ' # The same declarations can be made for test programs, which are ' ,& & ' # executed with the \"fpm test\" command and are not build when your ' ,& & ' # package is used as a dependency by other packages. These are ' ,& & ' # typically unit tests of the package only used during package ' ,& & ' # development. ' ,& & ' ' ,& & 'name=\"runTests\" ' ,& & 'source-dir=\"test\" ' ,& & 'main=\"check.f90\" ' ,& & ' ' ,& & ' # you may repeat this pattern to add additional explicit test program ' ,& & ' # parameters. The following example contains a sample of all accepted ' ,& & ' # options. ' ,& & ' ' ,& & '#[[ test ]] ' ,& & '#name = \"tester\" ' ,& & '#source-dir=\"test\" ' ,& & '#main=\"tester.f90\" ' ,& & '#link = [\"blas\", \"lapack\"] ' ,& & '#[test.dependencies] ' ,& & '#M_CLI2 = { git = \"https://github.com/urbanjost/M_CLI2.git\" } ' ,& & '#M_io = { git = \"https://github.com/urbanjost/M_io.git\" } ' ,& & '#M_system= { git = \"https://github.com/urbanjost/M_system.git\" } ' ,& & '' ] endif littlefile = [ character ( len = 80 ) :: & & 'program check' , & & 'implicit none' , & & '' , & & 'print *, \"Put some tests in here!\"' , & & 'end program check' ] ! create NAME/test/check.f90 call warnwrite ( join_path ( settings % name , 'test/check.f90' ), littlefile ) endif if ( settings % with_bare ) then elseif ( settings % with_example ) then ! create NAME/example or stop call mkdir ( join_path ( settings % name , 'example' )) ! create next section of fpm.toml if ( settings % with_full ) then tomlfile = [ character ( len = 80 ) :: tomlfile , & & '[[example]] ' ,& & ' ' ,& & ' # Example applications for a project are defined here. ' ,& & ' # These are run via \"fpm run --example NAME\" and like the ' ,& & ' # test applications, are not built when this package is used as a ' ,& & ' # dependency by other packages. ' ,& & ' ' ,& & 'name=\"demo\" ' ,& & 'source-dir=\"example\" ' ,& & 'main=\"demo.f90\" ' ,& & ' ' ,& & ' # ' ,& & ' # you may add additional programs to the example table. The following ' ,& & ' # example contains a sample of all accepted options ' ,& & ' ' ,& & '#[[ example ]] ' ,& & '#name = \"example-tool\" ' ,& & '#source-dir=\"example\" ' ,& & '#main=\"tool.f90\" ' ,& & '#link = \"z\" ' ,& & '#[example.dependencies] ' ,& & '#M_kracken95 = { git = \"https://github.com/urbanjost/M_kracken95.git\" } ' ,& & '#datetime = {git = \"https://github.com/wavebitscientific/datetime-fortran.git\" }' ,& & '' ] endif littlefile = [ character ( len = 80 ) :: & & 'program demo' , & & 'implicit none' , & & '' , & & 'print *, \"Put some examples in here!\"' , & & 'end program demo' ] ! create NAME/example/demo.f90 call warnwrite ( join_path ( settings % name , 'example/demo.f90' ), littlefile ) endif ! now that built it write NAME/fpm.toml if ( allocated ( tomlfile ) ) then call validate_toml_data ( tomlfile ) call warnwrite ( join_path ( settings % name , 'fpm.toml' ), tomlfile ) else call create_verified_basic_manifest ( join_path ( settings % name , 'fpm.toml' )) endif ! assumes git(1) is installed and in path if ( which ( 'git' ) /= '' ) then call run ( 'git init ' // settings % name ) endif contains function git_metadata ( what ) result ( returned ) !> get metadata values such as email address and git name from git(1) or return appropriate default use fpm_filesystem , only : get_temp_filename , getline character ( len =* ), intent ( in ) :: what ! keyword designating what git metatdata to query character ( len = :), allocatable :: returned ! value to return for requested keyword character ( len = :), allocatable :: command character ( len = :), allocatable :: temp_filename character ( len = :), allocatable :: iomsg character ( len = :), allocatable :: temp_value integer :: stat , unit temp_filename = get_temp_filename () ! for known keywords set default value for RETURNED and associated git(1) command for query select case ( what ) case ( 'uname' ) returned = \"Jane Doe\" command = \"git config --get user.name > \" // temp_filename case ( 'email' ) returned = \"jane.doe@example.com\" command = \"git config --get user.email > \" // temp_filename case default write ( stderr , '(*(g0,1x))' )& & ' *git_metadata* unknown metadata name ' , trim ( what ) returned = '' return end select ! Execute command if git(1) is in command path if ( which ( 'git' ) /= '' ) then call run ( command , exitstat = stat ) if ( stat /= 0 ) then ! If command failed just return default return else ! Command did not return an error so try to read expected output file open ( file = temp_filename , newunit = unit , iostat = stat ) if ( stat == 0 ) then ! Read file into a scratch variable until status of doing so is checked call getline ( unit , temp_value , stat , iomsg ) if ( stat == 0 . and . temp_value /= '' ) then ! Return output from successful command returned = temp_value endif endif ! Always do the CLOSE because a failed open has unpredictable results. ! Add IOSTAT so a failed close does not cause program to stop close ( unit , status = \"delete\" , iostat = stat ) endif endif end function git_metadata subroutine create_verified_basic_manifest ( filename ) !> create a basic but verified default manifest file use fpm_toml , only : toml_table , toml_serialize , set_value use fpm_manifest_package , only : package_config_t , new_package use fpm_error , only : error_t implicit none character ( len =* ), intent ( in ) :: filename type ( toml_table ) :: table type ( package_config_t ) :: package type ( error_t ), allocatable :: error integer :: lun character ( len = 8 ) :: date character (:), allocatable :: output if ( exists ( filename )) then write ( stderr , '(*(g0,1x))' ) ' ' , filename ,& & 'already exists. Not overwriting' return endif !> get date to put into metadata in manifest file \"fpm.toml\" call date_and_time ( DATE = date ) table = toml_table () call fileopen ( filename , lun ) ! fileopen stops on error call set_value ( table , \"name\" , BNAME ) call set_value ( table , \"version\" , \"0.1.0\" ) call set_value ( table , \"license\" , \"license\" ) call set_value ( table , \"author\" , git_metadata ( 'uname' )) call set_value ( table , \"maintainer\" , git_metadata ( 'email' )) call set_value ( table , \"copyright\" , 'Copyright ' // date ( 1 : 4 ) // ', ' // git_metadata ( 'uname' )) ! continue building of manifest ! ... call new_package ( package , table , error = error ) if ( allocated ( error )) call fpm_stop ( 3 , '' ) output = toml_serialize ( table ) if ( settings % verbose ) then print '(a)' , output endif write ( lun , '(a)' ) output call fileclose ( lun ) ! fileopen stops on error end subroutine create_verified_basic_manifest subroutine validate_toml_data ( input ) !> verify a string array is a valid fpm.toml file ! use tomlf , only : toml_load use fpm_toml , only : toml_table , toml_serialize implicit none character ( kind = tfc , len = :), intent ( in ), allocatable :: input (:) character ( len = 1 ), parameter :: nl = new_line ( 'a' ) type ( toml_table ), allocatable :: table character ( kind = tfc , len = :), allocatable :: joined_string ! you have to add a newline character by using the intrinsic ! function `new_line(\"a\")` to get the lines processed correctly. joined_string = join ( input , right = nl ) if ( allocated ( table )) deallocate ( table ) call toml_load ( table , joined_string ) if ( allocated ( table )) then if ( settings % verbose ) then ! If the TOML file is successfully parsed the table will be allocated and ! can be written by `toml_serialize` to the standard output print '(a)' , toml_serialize ( table ) endif call table % destroy endif end subroutine validate_toml_data end subroutine cmd_new end module fpm_cmd_new","tags":"","loc":"sourcefile/new.f90.html"},{"title":"fpm_settings.f90 – Fortran-lang/fpm","text":"Source Code !> Manages global settings which are defined in the global config file. module fpm_settings use fpm_filesystem , only : exists , join_path , get_local_prefix , is_absolute_path , mkdir use fpm_environment , only : os_is_unix use fpm_error , only : error_t , fatal_error use fpm_toml , only : toml_table , toml_error , toml_stat , get_value , toml_load , check_keys use fpm_os , only : get_current_directory , change_directory , get_absolute_path , convert_to_absolute_path implicit none private public :: fpm_global_settings , get_global_settings , get_registry_settings , official_registry_base_url character ( * ), parameter :: official_registry_base_url = 'https://fpm-registry.vercel.app' character ( * ), parameter :: default_config_file_name = 'config.toml' type :: fpm_global_settings !> Path to the global config file excluding the file name. character ( len = :), allocatable :: path_to_config_folder !> Name of the global config file. The default is `config.toml`. character ( len = :), allocatable :: config_file_name !> Registry configs. type ( fpm_registry_settings ), allocatable :: registry_settings contains procedure :: has_custom_location , full_path , path_to_config_folder_or_empty end type type :: fpm_registry_settings !> The path to the local registry. If allocated, the local registry !> will be used instead of the remote registry and replaces the !> local cache. character ( len = :), allocatable :: path !> The URL to the remote registry. Can be used to get packages !> from the official or a custom registry. character ( len = :), allocatable :: url !> The path to the cache folder. If not specified, the default cache !> folders are `~/.local/share/fpm/dependencies` on Unix and !> `%APPDATA%\\local\\fpm\\dependencies` on Windows. !> Cannot be used together with `path`. character ( len = :), allocatable :: cache_path end type contains !> Obtain global settings from the global config file. subroutine get_global_settings ( global_settings , error ) !> Global settings to be obtained. type ( fpm_global_settings ), intent ( inout ) :: global_settings !> Error reading config file. type ( error_t ), allocatable , intent ( out ) :: error !> TOML table to be filled with global config settings. type ( toml_table ), allocatable :: table !> Error parsing to TOML table. type ( toml_error ), allocatable :: parse_error type ( toml_table ), pointer :: registry_table integer :: stat ! Use custom path to the config file if it was specified. if ( global_settings % has_custom_location ()) then ! Throw error if folder doesn't exist. if (. not . exists ( global_settings % path_to_config_folder )) then call fatal_error ( error , \"Folder not found: '\" // global_settings % path_to_config_folder // \"'.\" ); return end if ! Throw error if the file doesn't exist. if (. not . exists ( global_settings % full_path ())) then call fatal_error ( error , \"File not found: '\" // global_settings % full_path () // \"'.\" ); return end if ! Make sure that the path to the global config file is absolute. call convert_to_absolute_path ( global_settings % path_to_config_folder , error ) if ( allocated ( error )) return else ! Use default path if it wasn't specified. if ( os_is_unix ()) then global_settings % path_to_config_folder = join_path ( get_local_prefix (), 'share' , 'fpm' ) else global_settings % path_to_config_folder = join_path ( get_local_prefix (), 'fpm' ) end if ! Use default file name. global_settings % config_file_name = default_config_file_name ! Apply default registry settings and return if config file doesn't exist. if (. not . exists ( global_settings % full_path ())) then call use_default_registry_settings ( global_settings ); return end if end if ! Load into TOML table. call toml_load ( table , global_settings % full_path (), error = parse_error ) if ( allocated ( parse_error )) then allocate ( error ); call move_alloc ( parse_error % message , error % message ); return end if call get_value ( table , 'registry' , registry_table , requested = . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error reading registry from config file '\" // & & global_settings % full_path () // \"'.\" ); return end if ! A registry table was found. if ( associated ( registry_table )) then call get_registry_settings ( registry_table , global_settings , error ) else call use_default_registry_settings ( global_settings ) end if end !> Default registry settings are typically applied if the config file doesn't exist or no registry table was found in !> the global config file. subroutine use_default_registry_settings ( global_settings ) type ( fpm_global_settings ), intent ( inout ) :: global_settings if (. not . allocated ( global_settings % registry_settings )) allocate ( global_settings % registry_settings ) global_settings % registry_settings % url = official_registry_base_url global_settings % registry_settings % cache_path = join_path ( global_settings % path_to_config_folder_or_empty (), & & 'dependencies' ) end !> Read registry settings from the global config file. subroutine get_registry_settings ( table , global_settings , error ) !> The [registry] subtable from the global config file. type ( toml_table ), target , intent ( inout ) :: table !> The global settings which can be filled with the registry settings. type ( fpm_global_settings ), intent ( inout ) :: global_settings !> Error handling. type ( error_t ), allocatable , intent ( out ) :: error character (:), allocatable :: path , url , cache_path integer :: stat !> List of valid keys for the dependency table. character ( * ), dimension ( * ), parameter :: valid_keys = [ character ( 10 ) :: & & 'path' , & & 'url' , & & 'cache_path' & & ] call check_keys ( table , valid_keys , error ) if ( allocated ( error )) return allocate ( global_settings % registry_settings ) if ( table % has_key ( 'path' )) then call get_value ( table , 'path' , path , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error reading registry path: '\" // path // \"'.\" ); return end if end if if ( allocated ( path )) then if ( is_absolute_path ( path )) then global_settings % registry_settings % path = path else ! Get canonical, absolute path on both Unix and Windows. call get_absolute_path ( join_path ( global_settings % path_to_config_folder_or_empty (), path ), & & global_settings % registry_settings % path , error ) if ( allocated ( error )) return ! Check if the path to the registry exists. if (. not . exists ( global_settings % registry_settings % path )) then call fatal_error ( error , \"Directory '\" // global_settings % registry_settings % path // & & \"' doesn't exist.\" ); return end if end if end if if ( table % has_key ( 'url' )) then call get_value ( table , 'url' , url , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error reading registry url: '\" // url // \"'.\" ); return end if end if if ( allocated ( url )) then ! Throw error when both path and url were provided. if ( allocated ( path )) then call fatal_error ( error , 'Do not provide both path and url to the registry.' ); return end if global_settings % registry_settings % url = url else if (. not . allocated ( path )) then global_settings % registry_settings % url = official_registry_base_url end if if ( table % has_key ( 'cache_path' )) then call get_value ( table , 'cache_path' , cache_path , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error reading path to registry cache: '\" // cache_path // \"'.\" ); return end if end if if ( allocated ( cache_path )) then ! Throw error when both path and cache_path were provided. if ( allocated ( path )) then call fatal_error ( error , \"Do not provide both 'path' and 'cache_path'.\" ); return end if if ( is_absolute_path ( cache_path )) then if (. not . exists ( cache_path )) call mkdir ( cache_path ) global_settings % registry_settings % cache_path = cache_path else cache_path = join_path ( global_settings % path_to_config_folder_or_empty (), cache_path ) if (. not . exists ( cache_path )) call mkdir ( cache_path ) ! Get canonical, absolute path on both Unix and Windows. call get_absolute_path ( cache_path , global_settings % registry_settings % cache_path , error ) if ( allocated ( error )) return end if else if (. not . allocated ( path )) then global_settings % registry_settings % cache_path = & join_path ( global_settings % path_to_config_folder_or_empty (), 'dependencies' ) end if end !> True if the global config file is not at the default location. elemental logical function has_custom_location ( self ) class ( fpm_global_settings ), intent ( in ) :: self has_custom_location = allocated ( self % path_to_config_folder ) . and . allocated ( self % config_file_name ) if (. not . has_custom_location ) return has_custom_location = len_trim ( self % path_to_config_folder ) > 0 . and . len_trim ( self % config_file_name ) > 0 end !> The full path to the global config file. function full_path ( self ) result ( result ) class ( fpm_global_settings ), intent ( in ) :: self character ( len = :), allocatable :: result result = join_path ( self % path_to_config_folder_or_empty (), self % config_file_name ) end !> The path to the global config directory. pure function path_to_config_folder_or_empty ( self ) class ( fpm_global_settings ), intent ( in ) :: self character ( len = :), allocatable :: path_to_config_folder_or_empty if ( allocated ( self % path_to_config_folder )) then path_to_config_folder_or_empty = self % path_to_config_folder else path_to_config_folder_or_empty = \"\" end if end end","tags":"","loc":"sourcefile/fpm_settings.f90.html"},{"title":"library.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for libraries. !> !> A library table can currently have the following fields !> !>```toml !>[library] !>source-dir = \"path\" !>include-dir = [\"path1\",\"path2\"] !>build-script = \"file\" !>``` module fpm_manifest_library use fpm_error , only : error_t , syntax_error use fpm_strings , only : string_t , string_cat , operator ( == ) use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list , serializable_t , set_value , & set_list , set_string , get_value , get_list implicit none private public :: library_config_t , new_library !> Configuration meta data for a library type , extends ( serializable_t ) :: library_config_t !> Source path prefix character ( len = :), allocatable :: source_dir !> Include path prefix type ( string_t ), allocatable :: include_dir (:) !> Alternative build script to be invoked character ( len = :), allocatable :: build_script contains !> Print information on this instance procedure :: info !> Serialization interface procedure :: serializable_is_same => library_is_same procedure :: dump_to_toml procedure :: load_from_toml end type library_config_t character ( * ), parameter , private :: class_name = 'library_config_t' contains !> Construct a new library configuration from a TOML data structure subroutine new_library ( self , table , error ) !> Instance of the library configuration type ( library_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"source-dir\" , self % source_dir , \"src\" ) call get_value ( table , \"build-script\" , self % build_script ) call get_list ( table , \"include-dir\" , self % include_dir , error ) if ( allocated ( error )) return ! Set default value of include-dir if not found in manifest if (. not . allocated ( self % include_dir )) then self % include_dir = [ string_t ( \"include\" )] end if end subroutine new_library !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_keys ( list ) ! table can be empty if ( size ( list ) < 1 ) return do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in library\" ) exit case ( \"source-dir\" , \"include-dir\" , \"build-script\" ) continue end select end do end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the library configuration class ( library_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Library target\" if ( allocated ( self % source_dir )) then write ( unit , fmt ) \"- source directory\" , self % source_dir end if if ( allocated ( self % include_dir )) then write ( unit , fmt ) \"- include directory\" , string_cat ( self % include_dir , \",\" ) end if if ( allocated ( self % build_script )) then write ( unit , fmt ) \"- custom build\" , self % build_script end if end subroutine info logical function library_is_same ( this , that ) class ( library_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that library_is_same = . false . select type ( other => that ) type is ( library_config_t ) if (. not . this % include_dir == other % include_dir ) return if (. not . allocated ( this % source_dir ). eqv . allocated ( other % source_dir )) return if (. not . this % source_dir == other % source_dir ) return if (. not . allocated ( this % build_script ). eqv . allocated ( other % build_script )) return if (. not . this % build_script == other % build_script ) return class default ! Not the same type return end select !> All checks passed! library_is_same = . true . end function library_is_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( library_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_string ( table , \"source-dir\" , self % source_dir , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"build-script\" , self % build_script , error , class_name ) if ( allocated ( error )) return call set_list ( table , \"include-dir\" , self % include_dir , error ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( library_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"source-dir\" , self % source_dir ) if ( allocated ( error )) return call get_value ( table , \"build-script\" , self % build_script ) if ( allocated ( error )) return call get_list ( table , \"include-dir\" , self % include_dir , error ) end subroutine load_from_toml end module fpm_manifest_library","tags":"","loc":"sourcefile/library.f90.html"},{"title":"fpm_compiler.F90 – Fortran-lang/fpm","text":"Source Code !># Define compiler command options !! !! This module defines compiler options to use for the debug and release builds. ! vendor Fortran C Module output Module include OpenMP Free for OSS ! compiler compiler directory directory ! Gnu gfortran gcc -J -I -fopenmp X ! Intel ifort icc -module -I -qopenmp X ! Intel(Windows) ifort icc /module:path /I /Qopenmp X ! Intel oneAPI ifx icx -module -I -qopenmp X ! PGI pgfortran pgcc -module -I -mp X ! NVIDIA nvfortran nvc -module -I -mp X ! LLVM flang flang clang -module -I -mp X ! LFortran lfortran --- -J -I --openmp X ! Lahey/Futjitsu lfc ? -M -I -openmp ? ! NAG nagfor ? -mdir -I -openmp x ! Cray crayftn craycc -J -I -homp ? ! IBM xlf90 ? -qmoddir -I -qsmp X ! Oracle/Sun ? ? -moddir= -M -xopenmp ? ! Silverfrost FTN95 ftn95 ? ? /MOD_PATH ? ? ! Elbrus ? lcc -J -I -fopenmp ? ! Hewlett Packard ? ? ? ? ? discontinued ! Watcom ? ? ? ? ? discontinued ! PathScale ? ? -module -I -mp discontinued ! G95 ? ? -fmod= -I -fopenmp discontinued ! Open64 ? ? -module -I -mp discontinued ! Unisys ? ? ? ? ? discontinued module fpm_compiler use , intrinsic :: iso_fortran_env , only : stderr => error_unit use fpm_environment , only : & get_os_type , & OS_LINUX , & OS_MACOS , & OS_WINDOWS , & OS_CYGWIN , & OS_SOLARIS , & OS_FREEBSD , & OS_OPENBSD , & OS_UNKNOWN use fpm_filesystem , only : join_path , basename , get_temp_filename , delete_file , unix_path , & & getline , run use fpm_strings , only : split , string_cat , string_t , str_ends_with , str_begins_with_str use fpm_manifest , only : package_config_t use fpm_error , only : error_t , fatal_error use fpm_toml , only : serializable_t , toml_table , set_string , set_value , toml_stat , get_value implicit none public :: compiler_t , new_compiler , archiver_t , new_archiver , get_macros public :: debug enum , bind ( C ) enumerator :: & id_unknown , & id_gcc , & id_f95 , & id_caf , & id_intel_classic_nix , & id_intel_classic_mac , & id_intel_classic_windows , & id_intel_llvm_nix , & id_intel_llvm_windows , & id_intel_llvm_unknown , & id_pgi , & id_nvhpc , & id_nag , & id_flang , & id_flang_new , & id_f18 , & id_ibmxl , & id_cray , & id_lahey , & id_lfortran end enum integer , parameter :: compiler_enum = kind ( id_unknown ) !> Definition of compiler object type , extends ( serializable_t ) :: compiler_t !> Identifier of the compiler integer ( compiler_enum ) :: id = id_unknown !> Path to the Fortran compiler character ( len = :), allocatable :: fc !> Path to the C compiler character ( len = :), allocatable :: cc !> Path to the C++ compiler character ( len = :), allocatable :: cxx !> Print all commands logical :: echo = . true . !> Verbose output of command logical :: verbose = . true . contains !> Get default compiler flags procedure :: get_default_flags !> Get flag for module output directories procedure :: get_module_flag !> Get flag for include directories procedure :: get_include_flag !> Get feature flag procedure :: get_feature_flag !> Get flags for the main linking command procedure :: get_main_flags !> Compile a Fortran object procedure :: compile_fortran !> Compile a C object procedure :: compile_c !> Compile a CPP object procedure :: compile_cpp !> Link executable procedure :: link !> Check whether compiler is recognized procedure :: is_unknown !> Check whether this is an Intel compiler procedure :: is_intel !> Check whether this is a GNU compiler procedure :: is_gnu !> Enumerate libraries, based on compiler and platform procedure :: enumerate_libraries !> Serialization interface procedure :: serializable_is_same => compiler_is_same procedure :: dump_to_toml => compiler_dump procedure :: load_from_toml => compiler_load !> Fortran feature support procedure :: check_fortran_source_runs procedure :: with_xdp procedure :: with_qp !> Return compiler name procedure :: name => compiler_name end type compiler_t !> Definition of archiver object type , extends ( serializable_t ) :: archiver_t !> Path to archiver character ( len = :), allocatable :: ar !> Use response files to pass arguments logical :: use_response_file = . false . !> Print all command logical :: echo = . true . !> Verbose output of command logical :: verbose = . true . contains !> Create static archive procedure :: make_archive !> Serialization interface procedure :: serializable_is_same => ar_is_same procedure :: dump_to_toml procedure :: load_from_toml end type archiver_t !> Create debug printout interface debug module procedure :: debug_compiler module procedure :: debug_archiver end interface debug character ( * ), parameter :: & flag_gnu_coarray = \" -fcoarray=single\" , & flag_gnu_backtrace = \" -fbacktrace\" , & flag_gnu_opt = \" -O3 -funroll-loops\" , & flag_gnu_debug = \" -g\" , & flag_gnu_pic = \" -fPIC\" , & flag_gnu_warn = \" -Wall -Wextra\" , & flag_gnu_check = \" -fcheck=bounds -fcheck=array-temps\" , & flag_gnu_limit = \" -fmax-errors=1\" , & flag_gnu_external = \" -Wimplicit-interface\" , & flag_gnu_openmp = \" -fopenmp\" , & flag_gnu_no_implicit_typing = \" -fimplicit-none\" , & flag_gnu_no_implicit_external = \" -Werror=implicit-interface\" , & flag_gnu_free_form = \" -ffree-form\" , & flag_gnu_fixed_form = \" -ffixed-form\" character ( * ), parameter :: & flag_pgi_backslash = \" -Mbackslash\" , & flag_pgi_traceback = \" -traceback\" , & flag_pgi_debug = \" -g\" , & flag_pgi_check = \" -Mbounds -Mchkptr -Mchkstk\" , & flag_pgi_warn = \" -Minform=inform\" , & flag_pgi_openmp = \" -mp\" , & flag_pgi_free_form = \" -Mfree\" , & flag_pgi_fixed_form = \" -Mfixed\" character ( * ), parameter :: & flag_ibmxl_backslash = \" -qnoescape\" character ( * ), parameter :: & flag_intel_backtrace = \" -traceback\" , & flag_intel_warn = \" -warn all\" , & flag_intel_check = \" -check all\" , & flag_intel_debug = \" -O0 -g\" , & flag_intel_opt = \" -O3\" , & flag_intel_fp = \" -fp-model precise -pc64\" , & flag_intel_align = \" -align all\" , & flag_intel_limit = \" -error-limit 1\" , & flag_intel_pthread = \" -reentrancy threaded\" , & flag_intel_nogen = \" -nogen-interfaces\" , & flag_intel_byterecl = \" -assume byterecl\" , & flag_intel_openmp = \" -qopenmp\" , & flag_intel_free_form = \" -free\" , & flag_intel_fixed_form = \" -fixed\" , & flag_intel_standard_compliance = \" -standard-semantics\" character ( * ), parameter :: & flag_intel_llvm_check = \" -check all,nouninit\" character ( * ), parameter :: & flag_intel_backtrace_win = \" /traceback\" , & flag_intel_warn_win = \" /warn:all\" , & flag_intel_check_win = \" /check:all\" , & flag_intel_debug_win = \" /Od /Z7\" , & flag_intel_opt_win = \" /O3\" , & flag_intel_fp_win = \" /fp:precise\" , & flag_intel_align_win = \" /align:all\" , & flag_intel_limit_win = \" /error-limit:1\" , & flag_intel_pthread_win = \" /reentrancy:threaded\" , & flag_intel_nogen_win = \" /nogen-interfaces\" , & flag_intel_byterecl_win = \" /assume:byterecl\" , & flag_intel_openmp_win = \" /Qopenmp\" , & flag_intel_free_form_win = \" /free\" , & flag_intel_fixed_form_win = \" /fixed\" , & flag_intel_standard_compliance_win = \" /standard-semantics\" character ( * ), parameter :: & flag_nag_coarray = \" -coarray=single\" , & flag_nag_pic = \" -PIC\" , & flag_nag_check = \" -C\" , & flag_nag_debug = \" -g -O0\" , & flag_nag_opt = \" -O4\" , & flag_nag_backtrace = \" -gline\" , & flag_nag_openmp = \" -openmp\" , & flag_nag_free_form = \" -free\" , & flag_nag_fixed_form = \" -fixed\" , & flag_nag_no_implicit_typing = \" -u\" character ( * ), parameter :: & flag_lfortran_opt = \" --fast\" , & flag_lfortran_openmp = \" --openmp\" , & flag_lfortran_implicit_typing = \" --implicit-typing\" , & flag_lfortran_implicit_external = \" --implicit-interface\" , & flag_lfortran_fixed_form = \" --fixed-form\" character ( * ), parameter :: & flag_cray_no_implicit_typing = \" -dl\" , & flag_cray_implicit_typing = \" -el\" , & flag_cray_fixed_form = \" -ffixed\" , & flag_cray_free_form = \" -ffree\" contains function get_default_flags ( self , release ) result ( flags ) class ( compiler_t ), intent ( in ) :: self logical , intent ( in ) :: release character ( len = :), allocatable :: flags if ( release ) then call get_release_compile_flags ( self % id , flags ) else call get_debug_compile_flags ( self % id , flags ) end if end function get_default_flags subroutine get_release_compile_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( out ) :: flags select case ( id ) case default flags = \"\" case ( id_caf ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit case ( id_gcc ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_coarray case ( id_f95 ) flags = & flag_gnu_opt // & flag_gnu_external // & flag_gnu_pic // & flag_gnu_limit case ( id_nvhpc ) flags = & flag_pgi_backslash case ( id_ibmxl ) flags = & flag_ibmxl_backslash case ( id_intel_classic_nix ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_classic_mac ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_classic_windows ) flags = & flag_intel_opt_win // & flag_intel_fp_win // & flag_intel_align_win // & flag_intel_limit_win // & flag_intel_pthread_win // & flag_intel_nogen_win // & flag_intel_byterecl_win case ( id_intel_llvm_nix ) flags = & flag_intel_opt // & flag_intel_fp // & flag_intel_align // & flag_intel_limit // & flag_intel_pthread // & flag_intel_nogen // & flag_intel_byterecl case ( id_intel_llvm_windows ) flags = & flag_intel_opt_win // & flag_intel_fp_win // & flag_intel_align_win // & flag_intel_limit_win // & flag_intel_pthread_win // & flag_intel_nogen_win // & flag_intel_byterecl_win case ( id_nag ) flags = & flag_nag_opt // & flag_nag_coarray // & flag_nag_pic case ( id_lfortran ) flags = & flag_lfortran_opt end select end subroutine get_release_compile_flags subroutine get_debug_compile_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( out ) :: flags select case ( id ) case default flags = \"\" case ( id_caf ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & flag_gnu_backtrace case ( id_gcc ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & flag_gnu_backtrace // & flag_gnu_coarray case ( id_f95 ) flags = & flag_gnu_warn // & flag_gnu_pic // & flag_gnu_limit // & flag_gnu_debug // & flag_gnu_check // & ' -Wno-maybe-uninitialized -Wno-uninitialized' // & flag_gnu_backtrace case ( id_nvhpc ) flags = & flag_pgi_warn // & flag_pgi_backslash // & flag_pgi_check // & flag_pgi_traceback case ( id_ibmxl ) flags = & flag_ibmxl_backslash case ( id_intel_classic_nix ) flags = & flag_intel_warn // & flag_intel_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_classic_mac ) flags = & flag_intel_warn // & flag_intel_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_classic_windows ) flags = & flag_intel_warn_win // & flag_intel_check_win // & flag_intel_limit_win // & flag_intel_debug_win // & flag_intel_byterecl_win // & flag_intel_backtrace_win case ( id_intel_llvm_nix ) flags = & flag_intel_warn // & flag_intel_llvm_check // & flag_intel_limit // & flag_intel_debug // & flag_intel_byterecl // & flag_intel_backtrace case ( id_intel_llvm_windows ) flags = & flag_intel_warn_win // & flag_intel_check_win // & flag_intel_limit_win // & flag_intel_debug_win // & flag_intel_byterecl_win case ( id_nag ) flags = & flag_nag_debug // & flag_nag_check // & flag_nag_backtrace // & flag_nag_coarray // & flag_nag_pic case ( id_lfortran ) flags = \"\" end select end subroutine get_debug_compile_flags pure subroutine set_cpp_preprocessor_flags ( id , flags ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( inout ) :: flags character ( len = :), allocatable :: flag_cpp_preprocessor !> Modify the flag_cpp_preprocessor on the basis of the compiler. select case ( id ) case default flag_cpp_preprocessor = \"\" case ( id_caf , id_gcc , id_f95 , id_nvhpc ) flag_cpp_preprocessor = \"-cpp\" case ( id_intel_classic_windows , id_intel_llvm_windows ) flag_cpp_preprocessor = \"/fpp\" case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , id_nag ) flag_cpp_preprocessor = \"-fpp\" case ( id_lfortran ) flag_cpp_preprocessor = \"--cpp\" end select flags = flag_cpp_preprocessor // flags end subroutine set_cpp_preprocessor_flags !> This function will parse and read the macros list and !> return them as defined flags. function get_macros ( id , macros_list , version ) result ( macros ) integer ( compiler_enum ), intent ( in ) :: id character ( len = :), allocatable , intent ( in ) :: version type ( string_t ), allocatable , intent ( in ) :: macros_list (:) character ( len = :), allocatable :: macros character ( len = :), allocatable :: macro_definition_symbol character (:), allocatable :: valued_macros (:) integer :: i if (. not . allocated ( macros_list )) then macros = \"\" return end if !> Set macro defintion symbol on the basis of compiler used select case ( id ) case default macro_definition_symbol = \" -D\" case ( id_intel_classic_windows , id_intel_llvm_windows ) macro_definition_symbol = \" /D\" end select !> Check if macros are not allocated. if (. not . allocated ( macros )) then macros = \"\" end if do i = 1 , size ( macros_list ) !> Split the macro name and value. call split ( macros_list ( i )% s , valued_macros , delimiters = \"=\" ) if ( size ( valued_macros ) > 1 ) then !> Check if the value of macro starts with '{' character. if ( str_begins_with_str ( trim ( valued_macros ( size ( valued_macros ))), \"{\" )) then !> Check if the value of macro ends with '}' character. if ( str_ends_with ( trim ( valued_macros ( size ( valued_macros ))), \"}\" )) then !> Check if the string contains \"version\" as substring. if ( index ( valued_macros ( size ( valued_macros )), \"version\" ) /= 0 ) then !> These conditions are placed in order to ensure proper spacing between the macros. macros = macros // macro_definition_symbol // trim ( valued_macros ( 1 )) // '=' // version cycle end if end if end if end if macros = macros // macro_definition_symbol // macros_list ( i )% s end do end function get_macros function get_include_flag ( self , path ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: flags select case ( self % id ) case default flags = \"-I \" // path case ( id_caf , id_gcc , id_f95 , id_cray , id_nvhpc , id_pgi , & & id_flang , id_flang_new , id_f18 , & & id_intel_classic_nix , id_intel_classic_mac , & & id_intel_llvm_nix , id_lahey , id_nag , id_ibmxl , & & id_lfortran ) flags = \"-I \" // path case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = \"/I\" // path end select end function get_include_flag function get_module_flag ( self , path ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: flags select case ( self % id ) case default flags = \"-module \" // path case ( id_caf , id_gcc , id_f95 , id_cray , id_lfortran ) flags = \"-J \" // path case ( id_nvhpc , id_pgi , id_flang ) flags = \"-module \" // path case ( id_flang_new , id_f18 ) flags = \"-module-dir \" // path case ( id_intel_classic_nix , id_intel_classic_mac , & & id_intel_llvm_nix ) flags = \"-module \" // path case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = \"/module:\" // path case ( id_lahey ) flags = \"-M \" // path case ( id_nag ) flags = \"-mdir \" // path case ( id_ibmxl ) flags = \"-qmoddir \" // path end select end function get_module_flag function get_feature_flag ( self , feature ) result ( flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: feature character ( len = :), allocatable :: flags flags = \"\" select case ( feature ) case ( \"no-implicit-typing\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_no_implicit_typing case ( id_nag ) flags = flag_nag_no_implicit_typing case ( id_cray ) flags = flag_cray_no_implicit_typing end select case ( \"implicit-typing\" ) select case ( self % id ) case ( id_cray ) flags = flag_cray_implicit_typing case ( id_lfortran ) flags = flag_lfortran_implicit_typing end select case ( \"no-implicit-external\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_no_implicit_external end select case ( \"implicit-external\" ) select case ( self % id ) case ( id_lfortran ) flags = flag_lfortran_implicit_external end select case ( \"free-form\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_free_form case ( id_pgi , id_nvhpc , id_flang ) flags = flag_pgi_free_form case ( id_nag ) flags = flag_nag_free_form case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , & & id_intel_llvm_unknown ) flags = flag_intel_free_form case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = flag_intel_free_form_win case ( id_cray ) flags = flag_cray_free_form end select case ( \"fixed-form\" ) select case ( self % id ) case ( id_caf , id_gcc , id_f95 ) flags = flag_gnu_fixed_form case ( id_pgi , id_nvhpc , id_flang ) flags = flag_pgi_fixed_form case ( id_nag ) flags = flag_nag_fixed_form case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , & & id_intel_llvm_unknown ) flags = flag_intel_fixed_form case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = flag_intel_fixed_form_win case ( id_cray ) flags = flag_cray_fixed_form case ( id_lfortran ) flags = flag_lfortran_fixed_form end select case ( \"default-form\" ) continue case default error stop \"Unknown feature '\" // feature // \"'\" end select end function get_feature_flag !> Get special flags for the main linker subroutine get_main_flags ( self , language , flags ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: language character ( len = :), allocatable , intent ( out ) :: flags flags = \"\" select case ( language ) case ( \"fortran\" ) flags = \"\" case ( \"c\" ) ! If the main program is on a C/C++ source, the Intel Fortran compiler requires option ! -nofor-main to avoid \"duplicate main\" errors. ! https://stackoverflow.com/questions/36221612/p3dfft-compilation-ifort-compiler-error-multiple-definiton-of-main select case ( self % id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix ) flags = '-nofor-main' case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = '/nofor-main' case ( id_pgi , id_nvhpc ) flags = '-Mnomain' end select case ( \"c++\" , \"cpp\" , \"cxx\" ) select case ( self % id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix ) flags = '-nofor-main' case ( id_intel_classic_windows , id_intel_llvm_windows ) flags = '/nofor-main' case ( id_pgi , id_nvhpc ) flags = '-Mnomain' end select case default error stop \"Unknown language '\" // language // '\", try \"fortran\", \"c\", \"c++\"' end select end subroutine get_main_flags subroutine get_default_c_compiler ( f_compiler , c_compiler ) character ( len =* ), intent ( in ) :: f_compiler character ( len = :), allocatable , intent ( out ) :: c_compiler integer ( compiler_enum ) :: id id = get_compiler_id ( f_compiler ) select case ( id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows ) c_compiler = 'icc' case ( id_intel_llvm_nix , id_intel_llvm_windows ) c_compiler = 'icx' case ( id_flang , id_flang_new , id_f18 ) c_compiler = 'clang' case ( id_ibmxl ) c_compiler = 'xlc' case ( id_lfortran ) c_compiler = 'cc' case ( id_gcc ) c_compiler = 'gcc' case default ! Fall-back to using Fortran compiler c_compiler = f_compiler end select end subroutine get_default_c_compiler !> Get C++ Compiler. subroutine get_default_cxx_compiler ( f_compiler , cxx_compiler ) character ( len =* ), intent ( in ) :: f_compiler character ( len = :), allocatable , intent ( out ) :: cxx_compiler integer ( compiler_enum ) :: id id = get_compiler_id ( f_compiler ) select case ( id ) case ( id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows ) cxx_compiler = 'icpc' case ( id_intel_llvm_nix , id_intel_llvm_windows ) cxx_compiler = 'icpx' case ( id_flang , id_flang_new , id_f18 ) cxx_compiler = 'clang++' case ( id_ibmxl ) cxx_compiler = 'xlc++' case ( id_lfortran ) cxx_compiler = 'cc' case ( id_gcc ) cxx_compiler = 'g++' case default ! Fall-back to using Fortran compiler cxx_compiler = f_compiler end select end subroutine get_default_cxx_compiler function get_compiler_id ( compiler ) result ( id ) character ( len =* ), intent ( in ) :: compiler integer ( kind = compiler_enum ) :: id character ( len = :), allocatable :: full_command , full_command_parts (:), command , output integer :: stat , io ! Check whether we are dealing with an MPI compiler wrapper first if ( check_compiler ( compiler , \"mpifort\" ) & & . or . check_compiler ( compiler , \"mpif90\" ) & & . or . check_compiler ( compiler , \"mpif77\" )) then output = get_temp_filename () call run ( compiler // \" -show > \" // output // \" 2>&1\" , & & echo = . false ., exitstat = stat ) if ( stat == 0 ) then open ( file = output , newunit = io , iostat = stat ) if ( stat == 0 ) call getline ( io , full_command , stat ) close ( io , iostat = stat ) ! If we get a command from the wrapper, we will try to identify it call split ( full_command , full_command_parts , delimiters = ' ' ) if ( size ( full_command_parts ) > 0 ) then command = trim ( full_command_parts ( 1 )) endif if ( allocated ( command )) then id = get_id ( command ) if ( id /= id_unknown ) return end if end if end if id = get_id ( compiler ) end function get_compiler_id function get_id ( compiler ) result ( id ) character ( len =* ), intent ( in ) :: compiler integer ( kind = compiler_enum ) :: id if ( check_compiler ( compiler , \"gfortran\" )) then id = id_gcc return end if if ( check_compiler ( compiler , \"f95\" )) then id = id_f95 return end if if ( check_compiler ( compiler , \"caf\" )) then id = id_caf return end if if ( check_compiler ( compiler , \"ifort\" )) then select case ( get_os_type ()) case default id = id_intel_classic_nix case ( OS_MACOS ) id = id_intel_classic_mac case ( OS_WINDOWS , OS_CYGWIN ) id = id_intel_classic_windows end select return end if if ( check_compiler ( compiler , \"ifx\" )) then select case ( get_os_type ()) case default id = id_intel_llvm_nix case ( OS_WINDOWS , OS_CYGWIN ) id = id_intel_llvm_windows end select return end if if ( check_compiler ( compiler , \"nvfortran\" )) then id = id_nvhpc return end if if ( check_compiler ( compiler , \"pgfortran\" ) & & . or . check_compiler ( compiler , \"pgf90\" ) & & . or . check_compiler ( compiler , \"pgf95\" )) then id = id_pgi return end if if ( check_compiler ( compiler , \"nagfor\" )) then id = id_nag return end if if ( check_compiler ( compiler , \"flang-new\" )) then id = id_flang_new return end if if ( check_compiler ( compiler , \"f18\" )) then id = id_f18 return end if if ( check_compiler ( compiler , \"flang\" )) then id = id_flang return end if if ( check_compiler ( compiler , \"xlf90\" )) then id = id_ibmxl return end if if ( check_compiler ( compiler , \"crayftn\" )) then id = id_cray return end if if ( check_compiler ( compiler , \"lfc\" )) then id = id_lahey return end if if ( check_compiler ( compiler , \"lfortran\" )) then id = id_lfortran return end if id = id_unknown end function get_id function check_compiler ( compiler , expected ) result ( match ) character ( len =* ), intent ( in ) :: compiler character ( len =* ), intent ( in ) :: expected logical :: match match = compiler == expected if (. not . match ) then match = index ( basename ( compiler ), expected ) > 0 end if end function check_compiler pure function is_unknown ( self ) class ( compiler_t ), intent ( in ) :: self logical :: is_unknown is_unknown = self % id == id_unknown end function is_unknown pure logical function is_intel ( self ) class ( compiler_t ), intent ( in ) :: self is_intel = any ( self % id == [ id_intel_classic_nix , id_intel_classic_mac , id_intel_classic_windows , & id_intel_llvm_nix , id_intel_llvm_windows , id_intel_llvm_unknown ]) end function is_intel pure logical function is_gnu ( self ) class ( compiler_t ), intent ( in ) :: self is_gnu = any ( self % id == [ id_f95 , id_gcc , id_caf ]) end function is_gnu !> !> Enumerate libraries, based on compiler and platform !> function enumerate_libraries ( self , prefix , libs ) result ( r ) class ( compiler_t ), intent ( in ) :: self character ( len =* ), intent ( in ) :: prefix type ( string_t ), intent ( in ) :: libs (:) character ( len = :), allocatable :: r if ( self % id == id_intel_classic_windows . or . & self % id == id_intel_llvm_windows ) then r = prefix // \" \" // string_cat ( libs , \".lib \" ) // \".lib\" else r = prefix // \" -l\" // string_cat ( libs , \" -l\" ) end if end function enumerate_libraries !> Create new compiler instance subroutine new_compiler ( self , fc , cc , cxx , echo , verbose ) !> New instance of the compiler type ( compiler_t ), intent ( out ) :: self !> Fortran compiler name or path character ( len =* ), intent ( in ) :: fc !> C compiler name or path character ( len =* ), intent ( in ) :: cc !> C++ Compiler name or path character ( len =* ), intent ( in ) :: cxx !> Echo compiler command logical , intent ( in ) :: echo !> Verbose mode: dump compiler output logical , intent ( in ) :: verbose self % id = get_compiler_id ( fc ) self % echo = echo self % verbose = verbose self % fc = fc if ( len_trim ( cc ) > 0 ) then self % cc = cc else call get_default_c_compiler ( self % fc , self % cc ) end if if ( len_trim ( cxx ) > 0 ) then self % cxx = cxx else call get_default_cxx_compiler ( self % fc , self % cxx ) end if end subroutine new_compiler !> Create new archiver instance subroutine new_archiver ( self , ar , echo , verbose ) !> New instance of the archiver type ( archiver_t ), intent ( out ) :: self !> User provided archiver command character ( len =* ), intent ( in ) :: ar !> Echo compiler command logical , intent ( in ) :: echo !> Verbose mode: dump compiler output logical , intent ( in ) :: verbose integer :: estat , os_type character ( len =* ), parameter :: arflags = \" -rs \" , libflags = \" /OUT:\" if ( len_trim ( ar ) > 0 ) then ! Check first for ar-like commands if ( check_compiler ( ar , \"ar\" )) then self % ar = ar // arflags end if ! Check for lib-like commands if ( check_compiler ( ar , \"lib\" )) then self % ar = ar // libflags end if ! Fallback and assume ar-like behaviour self % ar = ar // arflags else os_type = get_os_type () if ( os_type /= OS_WINDOWS . and . os_type /= OS_UNKNOWN ) then self % ar = \"ar\" // arflags else ! Attempt \"ar\" call execute_command_line ( \"ar --version > \" // get_temp_filename () // \" 2>&1\" , & & exitstat = estat ) if ( estat == 0 ) then self % ar = \"ar\" // arflags else ! Then \"gcc-ar\" call execute_command_line ( \"gcc-ar --version > \" // get_temp_filename () // \" 2>&1\" , & & exitstat = estat ) if ( estat /= 0 ) then self % ar = \"lib\" // libflags else self % ar = \"gcc-ar\" // arflags end if endif end if end if self % use_response_file = os_type == OS_WINDOWS self % echo = echo self % verbose = verbose end subroutine new_archiver !> Compile a Fortran object subroutine compile_fortran ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % fc // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_fortran !> Compile a C object subroutine compile_c ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % cc // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_c !> Compile a CPP object subroutine compile_cpp ( self , input , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Source file input character ( len =* ), intent ( in ) :: input !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % cxx // \" -c \" // input // \" \" // args // \" -o \" // output , & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine compile_cpp !> Link an executable subroutine link ( self , output , args , log_file , stat ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Output file of object character ( len =* ), intent ( in ) :: output !> Arguments for compiler character ( len =* ), intent ( in ) :: args !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat call run ( self % fc // \" \" // args // \" -o \" // output , echo = self % echo , & & verbose = self % verbose , redirect = log_file , exitstat = stat ) end subroutine link !> Create an archive !> @todo For Windows OS, use the local `delete_file_win32` in stead of `delete_file`. !> This may be related to a bug in Mingw64-openmp and is expected to be resolved in the future, !> see issue #707, #708 and #808. subroutine make_archive ( self , output , args , log_file , stat ) !> Instance of the archiver object class ( archiver_t ), intent ( in ) :: self !> Name of the archive to generate character ( len =* ), intent ( in ) :: output !> Object files to include into the archive type ( string_t ), intent ( in ) :: args (:) !> Compiler output log file character ( len =* ), intent ( in ) :: log_file !> Status flag integer , intent ( out ) :: stat if ( self % use_response_file ) then call write_response_file ( output // \".resp\" , args ) call run ( self % ar // output // \" @\" // output // \".resp\" , echo = self % echo , & & verbose = self % verbose , redirect = log_file , exitstat = stat ) call delete_file_win32 ( output // \".resp\" ) else call run ( self % ar // output // \" \" // string_cat ( args , \" \" ), & & echo = self % echo , verbose = self % verbose , redirect = log_file , exitstat = stat ) end if contains subroutine delete_file_win32 ( file ) character ( len =* ), intent ( in ) :: file logical :: exist integer :: unit , iostat inquire ( file = file , exist = exist ) if ( exist ) then open ( file = file , newunit = unit ) close ( unit , status = 'delete' , iostat = iostat ) end if end subroutine delete_file_win32 end subroutine make_archive !> Response files allow to read command line options from files. !> Whitespace is used to separate the arguments, we will use newlines !> as separator to create readable response files which can be inspected !> in case of errors. subroutine write_response_file ( name , argv ) character ( len =* ), intent ( in ) :: name type ( string_t ), intent ( in ) :: argv (:) integer :: iarg , io open ( file = name , newunit = io , status = 'replace' ) do iarg = 1 , size ( argv ) write ( io , '(a)' ) unix_path ( argv ( iarg )% s ) end do close ( io ) end subroutine write_response_file !> String representation of a compiler object pure function debug_compiler ( self ) result ( repr ) !> Instance of the compiler object type ( compiler_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: repr repr = 'fc=\"' // self % fc // '\", cc=\"' // self % cc // '\"' end function debug_compiler !> String representation of an archiver object pure function debug_archiver ( self ) result ( repr ) !> Instance of the archiver object type ( archiver_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: repr repr = 'ar=\"' // self % ar // '\"' end function debug_archiver !> Check that two archiver_t objects are equal logical function ar_is_same ( this , that ) class ( archiver_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that ar_is_same = . false . select type ( other => that ) type is ( archiver_t ) if (. not .( this % ar == other % ar )) return if (. not .( this % use_response_file . eqv . other % use_response_file )) return if (. not .( this % echo . eqv . other % echo )) return if (. not .( this % verbose . eqv . other % verbose )) return class default ! Not the same type return end select !> All checks passed! ar_is_same = . true . end function ar_is_same !> Dump dependency to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( archiver_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error !> Path to archiver call set_string ( table , \"ar\" , self % ar , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"use-response-file\" , self % use_response_file , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"echo\" , self % echo , error , 'archiver_t' ) if ( allocated ( error )) return call set_value ( table , \"verbose\" , self % verbose , error , 'archiver_t' ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read dependency from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( archiver_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"ar\" , self % ar ) call get_value ( table , \"use-response-file\" , self % use_response_file , error , 'archiver_t' ) if ( allocated ( error )) return call get_value ( table , \"echo\" , self % echo , error , 'archiver_t' ) if ( allocated ( error )) return call get_value ( table , \"verbose\" , self % verbose , error , 'archiver_t' ) if ( allocated ( error )) return end subroutine load_from_toml !> Check that two compiler_t objects are equal logical function compiler_is_same ( this , that ) class ( compiler_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that compiler_is_same = . false . select type ( other => that ) type is ( compiler_t ) if (. not .( this % id == other % id )) return if (. not .( this % fc == other % fc )) return if (. not .( this % cc == other % cc )) return if (. not .( this % cxx == other % cxx )) return if (. not .( this % echo . eqv . other % echo )) return if (. not .( this % verbose . eqv . other % verbose )) return class default ! Not the same type return end select !> All checks passed! compiler_is_same = . true . end function compiler_is_same !> Dump dependency to toml table subroutine compiler_dump ( self , table , error ) !> Instance of the serializable object class ( compiler_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: ierr call set_value ( table , \"id\" , self % id , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"fc\" , self % fc , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"cc\" , self % cc , error , 'compiler_t' ) if ( allocated ( error )) return call set_string ( table , \"cxx\" , self % cxx , error , 'compiler_t' ) if ( allocated ( error )) return call set_value ( table , \"echo\" , self % echo , error , 'compiler_t' ) if ( allocated ( error )) return call set_value ( table , \"verbose\" , self % verbose , error , 'compiler_t' ) if ( allocated ( error )) return end subroutine compiler_dump !> Read dependency from toml table (no checks made at this stage) subroutine compiler_load ( self , table , error ) !> Instance of the serializable object class ( compiler_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"id\" , self % id , error , 'compiler_t' ) if ( allocated ( error )) return call get_value ( table , \"fc\" , self % fc ) call get_value ( table , \"cc\" , self % cc ) call get_value ( table , \"cxx\" , self % cxx ) call get_value ( table , \"echo\" , self % echo , error , 'compiler_t' ) if ( allocated ( error )) return call get_value ( table , \"verbose\" , self % verbose , error , 'compiler_t' ) if ( allocated ( error )) return end subroutine compiler_load !> Return a compiler name string pure function compiler_name ( self ) result ( name ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Representation as string character ( len = :), allocatable :: name select case ( self % id ) case ( id_gcc ); name = \"gfortran\" case ( id_f95 ); name = \"f95\" case ( id_caf ); name = \"caf\" case ( id_intel_classic_nix ); name = \"ifort\" case ( id_intel_classic_mac ); name = \"ifort\" case ( id_intel_classic_windows ); name = \"ifort\" case ( id_intel_llvm_nix ); name = \"ifx\" case ( id_intel_llvm_windows ); name = \"ifx\" case ( id_intel_llvm_unknown ); name = \"ifx\" case ( id_pgi ); name = \"pgfortran\" case ( id_nvhpc ); name = \"nvfortran\" case ( id_nag ); name = \"nagfor\" case ( id_flang ); name = \"flang\" case ( id_flang_new ); name = \"flang-new\" case ( id_f18 ); name = \"f18\" case ( id_ibmxl ); name = \"xlf90\" case ( id_cray ); name = \"crayftn\" case ( id_lahey ); name = \"lfc\" case ( id_lfortran ); name = \"lFortran\" case default ; name = \"invalid/unknown\" end select end function compiler_name !> Run a single-source Fortran program using the current compiler !> Compile a Fortran object logical function check_fortran_source_runs ( self , input ) result ( success ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self !> Program Source character ( len =* ), intent ( in ) :: input integer :: stat , unit character (:), allocatable :: source , object , logf , exe success = . false . !> Create temporary source file exe = get_temp_filename () source = exe // '.f90' object = exe // '.o' logf = exe // '.log' open ( newunit = unit , file = source , action = 'readwrite' , iostat = stat ) if ( stat /= 0 ) return !> Write contents write ( unit , * ) input close ( unit ) !> Compile and link program call self % compile_fortran ( source , object , self % get_default_flags ( release = . false .), logf , stat ) if ( stat == 0 ) & call self % link ( exe , self % get_default_flags ( release = . false .) // \" \" // object , logf , stat ) !> Run and retrieve exit code if ( stat == 0 ) & call run ( exe , echo = . false ., exitstat = stat , verbose = . false ., redirect = logf ) !> Successful exit on 0 exit code success = stat == 0 !> Delete files open ( newunit = unit , file = source , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = object , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = logf , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) open ( newunit = unit , file = exe , action = 'readwrite' , iostat = stat ) close ( unit , status = 'delete' ) end function check_fortran_source_runs !> Check if the current compiler supports 128-bit real precision logical function with_qp ( self ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self with_qp = self % check_fortran_source_runs & ( 'if (selected_real_kind(33) == -1) stop 1; end' ) end function with_qp !> Check if the current compiler supports 80-bit \"extended\" real precision logical function with_xdp ( self ) !> Instance of the compiler object class ( compiler_t ), intent ( in ) :: self with_xdp = self % check_fortran_source_runs & ( 'if (any(selected_real_kind(18) == [-1, selected_real_kind(33)])) stop 1; end' ) end function with_xdp end module fpm_compiler","tags":"","loc":"sourcefile/fpm_compiler.f90.html"},{"title":"error.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of basic error handling. module fpm_error use , intrinsic :: iso_fortran_env , only : stdin => input_unit , stdout => output_unit , stderr => error_unit use fpm_strings , only : is_fortran_name , to_fortran_name implicit none private public :: error_t public :: fatal_error , syntax_error , file_not_found_error public :: file_parse_error public :: bad_name_error public :: fpm_stop !> Data type defining an error type :: error_t !> Error message character ( len = :), allocatable :: message end type error_t contains !> Generic fatal runtime error subroutine fatal_error ( error , message ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message character ( len =* ), intent ( in ) :: message allocate ( error ) error % message = message end subroutine fatal_error subroutine syntax_error ( error , message ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message character ( len =* ), intent ( in ) :: message allocate ( error ) error % message = message end subroutine syntax_error function bad_name_error ( error , label , name ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Error message label to add to message character ( len =* ), intent ( in ) :: label !> name value to check character ( len =* ), intent ( in ) :: name logical :: bad_name_error if (. not . is_fortran_name ( to_fortran_name ( name ))) then bad_name_error = . true . allocate ( error ) error % message = 'manifest file syntax error: ' // label // ' name must be composed only of & &alphanumerics, \"-\" and \"_\" and start with a letter ::' // name else bad_name_error = . false . endif end function bad_name_error !> Error created when a file is missing or not found subroutine file_not_found_error ( error , file_name ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Name of the missing file character ( len =* ), intent ( in ) :: file_name allocate ( error ) error % message = \"'\" // file_name // \"' could not be found, check if the file exists\" end subroutine file_not_found_error !> Error created when file parsing fails subroutine file_parse_error ( error , file_name , message , line_num , & line_string , line_col ) !> Instance of the error data type ( error_t ), allocatable , intent ( out ) :: error !> Name of file character ( len =* ), intent ( in ) :: file_name !> Parse error message character ( len =* ), intent ( in ) :: message !> Line number of parse error integer , intent ( in ), optional :: line_num !> Line context string character ( len =* ), intent ( in ), optional :: line_string !> Line context column integer , intent ( in ), optional :: line_col character ( 50 ) :: temp_string allocate ( error ) error % message = 'Parse error: ' // message // new_line ( 'a' ) error % message = error % message // file_name if ( present ( line_num )) then write ( temp_string , '(I0)' ) line_num error % message = error % message // ':' // trim ( temp_string ) end if if ( present ( line_col )) then if ( line_col > 0 ) then write ( temp_string , '(I0)' ) line_col error % message = error % message // ':' // trim ( temp_string ) end if end if if ( present ( line_string )) then error % message = error % message // new_line ( 'a' ) error % message = error % message // ' | ' // line_string if ( present ( line_col )) then if ( line_col > 0 ) then error % message = error % message // new_line ( 'a' ) error % message = error % message // ' | ' // repeat ( ' ' , line_col - 1 ) // '^' end if end if end if end subroutine file_parse_error subroutine fpm_stop ( value , message ) ! TODO: if verbose mode, call ERROR STOP instead of STOP ! TODO: if M_escape is used, add color ! to work with older compilers might need a case statement for values !> value to use on STOP integer , intent ( in ) :: value !> Error message character ( len =* ), intent ( in ) :: message integer :: iostat if ( message /= '' ) then flush ( unit = stderr , iostat = iostat ) flush ( unit = stdout , iostat = iostat ) if ( value > 0 ) then write ( stderr , '(\" \",a)' ) trim ( message ) else write ( stderr , '(\" \",a)' ) trim ( message ) endif flush ( unit = stderr , iostat = iostat ) endif stop value end subroutine fpm_stop end module fpm_error","tags":"","loc":"sourcefile/error.f90.html"},{"title":"fpm_release.F90 – Fortran-lang/fpm","text":"Source Code !># Release parameters !> Module fpm_release contains public constants storing this build's unique version IDs module fpm_release use fpm_versioning , only : version_t , new_version use fpm_error , only : error_t , fpm_stop implicit none private public :: fpm_version public :: version_t contains !> Return the current fpm version from fpm_version_ID as a version type type ( version_t ) function fpm_version () type ( error_t ), allocatable :: error ! Fallback to last known version in case of undefined macro #ifndef FPM_RELEASE_VERSION # define FPM_RELEASE_VERSION 0.10.1 #endif ! Accept solution from https://stackoverflow.com/questions/31649691/stringify-macro-with-gnu-gfortran ! which provides the \"easiest\" way to pass a macro to a string in Fortran complying with both ! gfortran's \"traditional\" cpp and the standard cpp syntaxes #ifdef __GFORTRAN__ /* traditional-cpp stringification */ # define STRINGIFY_START(X) \"& # define STRINGIFY_END(X) &X\" #else /* default stringification */ # define STRINGIFY_(X) #X # define STRINGIFY_START(X) & # define STRINGIFY_END(X) STRINGIFY_(X) #endif character ( len = :), allocatable :: ver_string ver_string = STRINGIFY_START ( FPM_RELEASE_VERSION ) STRINGIFY_END ( FPM_RELEASE_VERSION ) call new_version ( fpm_version , ver_string , error ) if ( allocated ( error )) call fpm_stop ( 1 , '*fpm*:internal error: cannot get version - ' // error % message ) end function fpm_version end module fpm_release","tags":"","loc":"sourcefile/fpm_release.f90.html"},{"title":"test.f90 – Fortran-lang/fpm","text":"Source Code !> Implementation of the meta data for a test. !> !> The test data structure is effectively a decorated version of an executable !> and shares most of its properties, except for the defaults and can be !> handled under most circumstances just like any other executable. !> !> A test table can currently have the following fields !> !>```toml !>[[ test ]] !>name = \"string\" !>source-dir = \"path\" !>main = \"file\" !>link = [\"lib\"] !>[test.dependencies] !>``` module fpm_manifest_test use fpm_manifest_dependency , only : new_dependencies use fpm_manifest_executable , only : executable_config_t use fpm_error , only : error_t , syntax_error , bad_name_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , get_list implicit none private public :: test_config_t , new_test !> Configuation meta data for an test type , extends ( executable_config_t ) :: test_config_t contains !> Print information on this instance procedure :: info end type test_config_t contains !> Construct a new test configuration from a TOML data structure subroutine new_test ( self , table , error ) !> Instance of the test configuration type ( test_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_table ), pointer :: child call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"name\" , self % name ) if (. not . allocated ( self % name )) then call syntax_error ( error , \"Could not retrieve test name\" ) return end if if ( bad_name_error ( error , 'test' , self % name )) then return endif call get_value ( table , \"source-dir\" , self % source_dir , \"test\" ) call get_value ( table , \"main\" , self % main , \"main.f90\" ) call get_value ( table , \"dependencies\" , child , requested = . false .) if ( associated ( child )) then call new_dependencies ( self % dependency , child , error = error ) if ( allocated ( error )) return end if call get_list ( table , \"link\" , self % link , error ) if ( allocated ( error )) return end subroutine new_test !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) logical :: name_present integer :: ikey name_present = . false . call table % get_keys ( list ) if ( size ( list ) < 1 ) then call syntax_error ( error , \"Test section does not provide sufficient entries\" ) return end if do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in test entry\" ) exit case ( \"name\" ) name_present = . true . case ( \"source-dir\" , \"main\" , \"dependencies\" , \"link\" ) continue end select end do if ( allocated ( error )) return if (. not . name_present ) then call syntax_error ( error , \"Test name is not provided, please add a name entry\" ) end if end subroutine check !> Write information on instance subroutine info ( self , unit , verbosity ) !> Instance of the test configuration class ( test_config_t ), intent ( in ) :: self !> Unit for IO integer , intent ( in ) :: unit !> Verbosity of the printout integer , intent ( in ), optional :: verbosity integer :: pr , ii character ( len =* ), parameter :: fmt = '(\"#\", 1x, a, t30, a)' , & & fmti = '(\"#\", 1x, a, t30, i0)' if ( present ( verbosity )) then pr = verbosity else pr = 1 end if if ( pr < 1 ) return write ( unit , fmt ) \"Test target\" if ( allocated ( self % name )) then write ( unit , fmt ) \"- name\" , self % name end if if ( allocated ( self % source_dir )) then if ( self % source_dir /= \"test\" . or . pr > 2 ) then write ( unit , fmt ) \"- source directory\" , self % source_dir end if end if if ( allocated ( self % main )) then if ( self % main /= \"main.f90\" . or . pr > 2 ) then write ( unit , fmt ) \"- test source\" , self % main end if end if if ( allocated ( self % dependency )) then if ( size ( self % dependency ) > 1 . or . pr > 2 ) then write ( unit , fmti ) \"- dependencies\" , size ( self % dependency ) end if do ii = 1 , size ( self % dependency ) call self % dependency ( ii )% info ( unit , pr - 1 ) end do end if end subroutine info end module fpm_manifest_test","tags":"","loc":"sourcefile/test.f90.html"},{"title":"fpm_meta.f90 – Fortran-lang/fpm","text":"Source Code !># The fpm meta-package model !> !> This is a wrapper data type that encapsulate all pre-processing information !> (compiler flags, linker libraries, etc.) required to correctly enable a package !> to use a core library. !> !> !>### Available core libraries !> !> - OpenMP !> - MPI !> - HDF5 !> - fortran-lang stdlib !> - fortran-lang minpack !> !> !> @note Core libraries are enabled in the [build] section of the fpm.toml manifest !> !> module fpm_meta use fpm_strings , only : string_t , len_trim , remove_newline_characters , str_begins_with_str , & str_ends_with use fpm_error , only : error_t , fatal_error , syntax_error , fpm_stop use fpm_compiler use fpm_model use fpm_command_line use fpm_manifest_dependency , only : dependency_config_t use fpm_git , only : git_target_branch , git_target_tag use fpm_manifest , only : package_config_t use fpm_environment , only : get_env , os_is_unix , set_env , delete_env use fpm_filesystem , only : run , get_temp_filename , getline , exists , canon_path , is_dir , get_dos_path use fpm_versioning , only : version_t , new_version , regex_version_from_text use fpm_os , only : get_absolute_path use fpm_pkg_config use shlex_module , only : shlex_split => split use regex_module , only : regex use iso_fortran_env , only : stdout => output_unit implicit none private public :: resolve_metapackages !> Type for describing a source file type , public :: metapackage_t !> Package version (if supported) type ( version_t ), allocatable :: version logical :: has_link_libraries = . false . logical :: has_link_flags = . false . logical :: has_build_flags = . false . logical :: has_fortran_flags = . false . logical :: has_c_flags = . false . logical :: has_cxx_flags = . false . logical :: has_include_dirs = . false . logical :: has_dependencies = . false . logical :: has_run_command = . false . logical :: has_external_modules = . false . !> List of compiler flags and options to be added type ( string_t ) :: flags type ( string_t ) :: fflags type ( string_t ) :: cflags type ( string_t ) :: cxxflags type ( string_t ) :: link_flags type ( string_t ) :: run_command type ( string_t ), allocatable :: incl_dirs (:) type ( string_t ), allocatable :: link_libs (:) type ( string_t ), allocatable :: external_modules (:) !> Special fortran features type ( fortran_features_t ), allocatable :: fortran !> List of Development dependency meta data. !> Metapackage dependencies are never exported from the model type ( dependency_config_t ), allocatable :: dependency (:) contains !> Clean metapackage structure procedure :: destroy !> Initialize the metapackage structure from its given name procedure :: new => init_from_name !> Add metapackage dependencies to the model procedure , private :: resolve_cmd procedure , private :: resolve_model procedure , private :: resolve_package_config generic :: resolve => resolve_cmd , resolve_model , resolve_package_config end type metapackage_t interface resolve_metapackages module procedure resolve_metapackage_model end interface resolve_metapackages integer , parameter :: MPI_TYPE_NONE = 0 integer , parameter :: MPI_TYPE_OPENMPI = 1 integer , parameter :: MPI_TYPE_MPICH = 2 integer , parameter :: MPI_TYPE_INTEL = 3 integer , parameter :: MPI_TYPE_MSMPI = 4 public :: MPI_TYPE_NAME !> Debugging information logical , parameter , private :: verbose = . false . integer , parameter , private :: LANG_FORTRAN = 1 integer , parameter , private :: LANG_C = 2 integer , parameter , private :: LANG_CXX = 3 character ( * ), parameter :: LANG_NAME ( * ) = [ character ( 7 ) :: 'Fortran' , 'C' , 'C++' ] contains !> Return a name for the MPI library pure function MPI_TYPE_NAME ( mpilib ) result ( name ) integer , intent ( in ) :: mpilib character ( len = :), allocatable :: name select case ( mpilib ) case ( MPI_TYPE_NONE ); name = \"none\" case ( MPI_TYPE_OPENMPI ); name = \"OpenMPI\" case ( MPI_TYPE_MPICH ); name = \"MPICH\" case ( MPI_TYPE_INTEL ); name = \"INTELMPI\" case ( MPI_TYPE_MSMPI ); name = \"MS-MPI\" case default ; name = \"UNKNOWN\" end select end function MPI_TYPE_NAME !> Clean the metapackage structure elemental subroutine destroy ( this ) class ( metapackage_t ), intent ( inout ) :: this this % has_link_libraries = . false . this % has_link_flags = . false . this % has_build_flags = . false . this % has_fortran_flags = . false . this % has_c_flags = . false . this % has_cxx_flags = . false . this % has_include_dirs = . false . this % has_dependencies = . false . this % has_run_command = . false . this % has_external_modules = . false . if ( allocated ( this % fortran )) deallocate ( this % fortran ) if ( allocated ( this % version )) deallocate ( this % version ) if ( allocated ( this % flags % s )) deallocate ( this % flags % s ) if ( allocated ( this % fflags % s )) deallocate ( this % fflags % s ) if ( allocated ( this % cflags % s )) deallocate ( this % cflags % s ) if ( allocated ( this % cxxflags % s )) deallocate ( this % cxxflags % s ) if ( allocated ( this % link_flags % s )) deallocate ( this % link_flags % s ) if ( allocated ( this % run_command % s )) deallocate ( this % run_command % s ) if ( allocated ( this % link_libs )) deallocate ( this % link_libs ) if ( allocated ( this % dependency )) deallocate ( this % dependency ) if ( allocated ( this % incl_dirs )) deallocate ( this % incl_dirs ) if ( allocated ( this % external_modules )) deallocate ( this % external_modules ) end subroutine destroy !> Initialize a metapackage from the given name subroutine init_from_name ( this , name , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this character ( * ), intent ( in ) :: name type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error !> Initialize metapackage by name select case ( name ) case ( \"openmp\" ); call init_openmp ( this , compiler , error ) case ( \"stdlib\" ); call init_stdlib ( this , compiler , error ) case ( \"minpack\" ); call init_minpack ( this , compiler , error ) case ( \"mpi\" ); call init_mpi ( this , compiler , error ) case ( \"hdf5\" ); call init_hdf5 ( this , compiler , error ) case default call syntax_error ( error , \"Package \" // name // \" is not supported in [metapackages]\" ) return end select end subroutine init_from_name !> Initialize OpenMP metapackage for the current system subroutine init_openmp ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error !> Cleanup call destroy ( this ) !> OpenMP has compiler flags this % has_build_flags = . true . this % has_link_flags = . true . !> OpenMP flags should be added to which_compiler : select case ( compiler % id ) case ( id_gcc , id_f95 ) this % flags = string_t ( flag_gnu_openmp ) this % link_flags = string_t ( flag_gnu_openmp ) case ( id_intel_classic_windows , id_intel_llvm_windows ) this % flags = string_t ( flag_intel_openmp_win ) this % link_flags = string_t ( flag_intel_openmp_win ) case ( id_intel_classic_nix , id_intel_classic_mac ,& id_intel_llvm_nix ) this % flags = string_t ( flag_intel_openmp ) this % link_flags = string_t ( flag_intel_openmp ) case ( id_pgi , id_nvhpc ) this % flags = string_t ( flag_pgi_openmp ) this % link_flags = string_t ( flag_pgi_openmp ) case ( id_ibmxl ) this % flags = string_t ( \" -qsmp=omp\" ) this % link_flags = string_t ( \" -qsmp=omp\" ) case ( id_nag ) this % flags = string_t ( flag_nag_openmp ) this % link_flags = string_t ( flag_nag_openmp ) case ( id_lfortran ) this % flags = string_t ( flag_lfortran_openmp ) this % link_flags = string_t ( flag_lfortran_openmp ) case default call fatal_error ( error , 'openmp not supported on compiler ' // compiler % name () // ' yet' ) end select which_compiler end subroutine init_openmp !> Initialize minpack metapackage for the current system subroutine init_minpack ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error !> Cleanup call destroy ( this ) !> minpack is queried as a dependency from the official repository this % has_dependencies = . true . allocate ( this % dependency ( 1 )) !> 1) minpack. There are no true releases currently. Fetch HEAD this % dependency ( 1 )% name = \"minpack\" this % dependency ( 1 )% git = git_target_tag ( \"https://github.com/fortran-lang/minpack\" , \"v2.0.0-rc.1\" ) if (. not . allocated ( this % dependency ( 1 )% git )) then call fatal_error ( error , 'cannot initialize git repo dependency for minpack metapackage' ) return end if end subroutine init_minpack !> Initialize stdlib metapackage for the current system subroutine init_stdlib ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error !> Cleanup call destroy ( this ) !> Stdlib is queried as a dependency from the official repository this % has_dependencies = . true . allocate ( this % dependency ( 2 )) !> 1) Test-drive this % dependency ( 1 )% name = \"test-drive\" this % dependency ( 1 )% git = git_target_branch ( \"https://github.com/fortran-lang/test-drive\" , \"v0.4.0\" ) if (. not . allocated ( this % dependency ( 1 )% git )) then call fatal_error ( error , 'cannot initialize test-drive git dependency for stdlib metapackage' ) return end if !> 2) stdlib this % dependency ( 2 )% name = \"stdlib\" this % dependency ( 2 )% git = git_target_branch ( \"https://github.com/fortran-lang/stdlib\" , \"stdlib-fpm\" ) if (. not . allocated ( this % dependency ( 2 )% git )) then call fatal_error ( error , 'cannot initialize git repo dependency for stdlib metapackage' ) return end if end subroutine init_stdlib ! Resolve metapackage dependencies into the command line settings subroutine resolve_cmd ( self , settings , error ) class ( metapackage_t ), intent ( in ) :: self class ( fpm_cmd_settings ), intent ( inout ) :: settings type ( error_t ), allocatable , intent ( out ) :: error ! Add customize run commands if ( self % has_run_command ) then select type ( cmd => settings ) class is ( fpm_run_settings ) ! includes fpm_test_settings ! Only override runner if user has not provided a custom one if (. not . len_trim ( cmd % runner ) > 0 ) cmd % runner = self % run_command % s end select endif end subroutine resolve_cmd ! Resolve metapackage dependencies into the model subroutine resolve_model ( self , model , error ) class ( metapackage_t ), intent ( in ) :: self type ( fpm_model_t ), intent ( inout ) :: model type ( error_t ), allocatable , intent ( out ) :: error ! Add global build flags, to apply to all sources if ( self % has_build_flags ) then model % fortran_compile_flags = model % fortran_compile_flags // self % flags % s model % c_compile_flags = model % c_compile_flags // self % flags % s model % cxx_compile_flags = model % cxx_compile_flags // self % flags % s endif ! Add language-specific flags if ( self % has_fortran_flags ) model % fortran_compile_flags = model % fortran_compile_flags // self % fflags % s if ( self % has_c_flags ) model % c_compile_flags = model % c_compile_flags // self % cflags % s if ( self % has_cxx_flags ) model % cxx_compile_flags = model % cxx_compile_flags // self % cxxflags % s if ( self % has_link_flags ) then model % link_flags = model % link_flags // ' ' // self % link_flags % s end if if ( self % has_link_libraries ) then model % link_libraries = [ model % link_libraries , self % link_libs ] end if if ( self % has_include_dirs ) then model % include_dirs = [ model % include_dirs , self % incl_dirs ] end if if ( self % has_external_modules ) then model % external_modules = [ model % external_modules , self % external_modules ] end if end subroutine resolve_model subroutine resolve_package_config ( self , package , error ) class ( metapackage_t ), intent ( in ) :: self type ( package_config_t ), intent ( inout ) :: package type ( error_t ), allocatable , intent ( out ) :: error ! All metapackage dependencies are added as dev-dependencies, ! as they may change if built upstream if ( self % has_dependencies ) then if ( allocated ( package % dev_dependency )) then package % dev_dependency = [ package % dev_dependency , self % dependency ] else package % dev_dependency = self % dependency end if end if ! Check if there are any special fortran requests which the package does not comply to if ( allocated ( self % fortran )) then if ( self % fortran % implicit_external . neqv . package % fortran % implicit_external ) then call fatal_error ( error , 'metapackage fortran error: metapackage ' // & dn ( self % fortran % implicit_external ) // ' require implicit-external, main package ' // & dn ( package % fortran % implicit_external )) return end if if ( self % fortran % implicit_typing . neqv . package % fortran % implicit_typing ) then call fatal_error ( error , 'metapackage fortran error: metapackage ' // & dn ( self % fortran % implicit_external ) // ' require implicit-typing, main package ' // & dn ( package % fortran % implicit_external )) return end if end if contains pure function dn ( bool ) logical , intent ( in ) :: bool character ( len = :), allocatable :: dn if ( bool ) then dn = \"does\" else dn = \"does not\" end if end function dn end subroutine resolve_package_config ! Add named metapackage dependency to the model subroutine add_metapackage_model ( model , package , settings , name , error ) type ( fpm_model_t ), intent ( inout ) :: model type ( package_config_t ), intent ( inout ) :: package class ( fpm_cmd_settings ), intent ( inout ) :: settings character ( * ), intent ( in ) :: name type ( error_t ), allocatable , intent ( out ) :: error type ( metapackage_t ) :: meta !> Init metapackage call meta % new ( name , model % compiler , error ) if ( allocated ( error )) return !> Add it into the model call meta % resolve ( model , error ) if ( allocated ( error )) return !> Add it into the package call meta % resolve ( package , error ) if ( allocated ( error )) return !> Add it into the settings call meta % resolve ( settings , error ) if ( allocated ( error )) return ! If we need to run executables, there should be an MPI runner if ( name == \"mpi\" ) then select type ( settings ) class is ( fpm_run_settings ) ! run, test if (. not . meta % has_run_command ) & call fatal_error ( error , \"cannot find a valid mpi runner on the local host\" ) end select endif end subroutine add_metapackage_model !> Resolve all metapackages into the package config subroutine resolve_metapackage_model ( model , package , settings , error ) type ( fpm_model_t ), intent ( inout ) :: model type ( package_config_t ), intent ( inout ) :: package class ( fpm_build_settings ), intent ( inout ) :: settings type ( error_t ), allocatable , intent ( out ) :: error ! Dependencies are added to the package config, so they're properly resolved ! into the dependency tree later. ! Flags are added to the model (whose compiler needs to be already initialized) if ( model % compiler % is_unknown ()) & write ( stdout , '(a)' ) ' compiler not initialized: metapackages may not be available' ! OpenMP if ( package % meta % openmp % on ) then call add_metapackage_model ( model , package , settings , \"openmp\" , error ) if ( allocated ( error )) return endif ! stdlib if ( package % meta % stdlib % on ) then call add_metapackage_model ( model , package , settings , \"stdlib\" , error ) if ( allocated ( error )) return endif ! minpack if ( package % meta % minpack % on ) then call add_metapackage_model ( model , package , settings , \"minpack\" , error ) if ( allocated ( error )) return endif ! Stdlib is not 100% thread safe. print a warning to the user if ( package % meta % stdlib % on . and . package % meta % openmp % on ) then write ( stdout , '(a)' ) ' both openmp and stdlib requested: some functions may not be thread-safe!' end if ! MPI if ( package % meta % mpi % on ) then call add_metapackage_model ( model , package , settings , \"mpi\" , error ) if ( allocated ( error )) return endif ! hdf5 if ( package % meta % hdf5 % on ) then call add_metapackage_model ( model , package , settings , \"hdf5\" , error ) if ( allocated ( error )) return endif end subroutine resolve_metapackage_model !> Initialize MPI metapackage for the current system subroutine init_mpi ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error type ( string_t ), allocatable :: c_wrappers (:), cpp_wrappers (:), fort_wrappers (:) type ( string_t ) :: output , fwrap , cwrap , cxxwrap character ( 256 ) :: msg_out character ( len = :), allocatable :: tokens (:) integer :: wcfit ( 3 ), mpilib ( 3 ), ic , icpp , i logical :: found !> Cleanup call destroy ( this ) !> Get all candidate MPI wrappers call mpi_wrappers ( compiler , fort_wrappers , c_wrappers , cpp_wrappers ) if ( verbose ) print 1 , size ( fort_wrappers ), size ( c_wrappers ), size ( cpp_wrappers ) call wrapper_compiler_fit ( fort_wrappers , c_wrappers , cpp_wrappers , compiler , wcfit , mpilib , error ) if ( allocated ( error ) . or . all ( wcfit == 0 )) then !> No wrapper compiler fit. Are we on Windows? use MSMPI-specific search found = msmpi_init ( this , compiler , error ) if ( allocated ( error )) return !> All attempts failed if (. not . found ) then call fatal_error ( error , \"cannot find MPI wrappers or libraries for \" // compiler % name () // \" compiler\" ) return endif else if ( wcfit ( LANG_FORTRAN ) > 0 ) fwrap = fort_wrappers ( wcfit ( LANG_FORTRAN )) if ( wcfit ( LANG_C ) > 0 ) cwrap = c_wrappers ( wcfit ( LANG_C )) if ( wcfit ( LANG_CXX ) > 0 ) cxxwrap = cpp_wrappers ( wcfit ( LANG_CXX )) !> If there's only an available Fortran wrapper, and the compiler's different than fpm's baseline !> fortran compiler suite, we still want to enable C language flags as that is most likely being !> ABI-compatible anyways. However, issues may arise. !> see e.g. Homebrew with clabng C/C++ and GNU fortran at https://gitlab.kitware.com/cmake/cmake/-/issues/18139 if ( wcfit ( LANG_FORTRAN ) > 0 . and . all ( wcfit ([ LANG_C , LANG_CXX ]) == 0 )) then cwrap = fort_wrappers ( wcfit ( LANG_FORTRAN )) cxxwrap = fort_wrappers ( wcfit ( LANG_FORTRAN )) end if if ( verbose ) print * , '+ MPI fortran wrapper: ' , fwrap % s if ( verbose ) print * , '+ MPI c wrapper: ' , cwrap % s if ( verbose ) print * , '+ MPI c++ wrapper: ' , cxxwrap % s !> Initialize MPI package from wrapper command call init_mpi_from_wrappers ( this , compiler , mpilib ( LANG_FORTRAN ), fwrap , cwrap , cxxwrap , error ) if ( allocated ( error )) return !> Request Fortran implicit typing if ( mpilib ( LANG_FORTRAN ) /= MPI_TYPE_INTEL ) then allocate ( this % fortran ) this % fortran % implicit_typing = . true . this % fortran % implicit_external = . true . endif end if !> Not all MPI implementations offer modules mpi and mpi_f08: hence, include them !> to the list of external modules, so they won't be requested as standard source files this % has_external_modules = . true . this % external_modules = [ string_t ( \"mpi\" ), string_t ( \"mpi_f08\" )] 1 format ( 'MPI wrappers found: fortran=' , i0 , ' c=' , i0 , ' c++=' , i0 ) end subroutine init_mpi !> Check if we're on a 64-bit environment !> Accept answer from https://stackoverflow.com/questions/49141093/get-system-information-with-fortran logical function is_64bit_environment () use iso_c_binding , only : c_intptr_t integer , parameter :: nbits = bit_size ( 0_c_intptr_t ) is_64bit_environment = nbits == 64 end function is_64bit_environment !> Check if there is a wrapper-compiler fit subroutine wrapper_compiler_fit ( fort_wrappers , c_wrappers , cpp_wrappers , compiler , wrap , mpi , error ) type ( string_t ), allocatable , intent ( in ) :: fort_wrappers (:), c_wrappers (:), cpp_wrappers (:) type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error integer , intent ( out ), dimension ( 3 ) :: wrap , mpi type ( error_t ), allocatable :: wrap_error wrap = 0 mpi = MPI_TYPE_NONE if ( size ( fort_wrappers ) > 0 ) & call mpi_compiler_match ( LANG_FORTRAN , fort_wrappers , compiler , wrap ( LANG_FORTRAN ), mpi ( LANG_FORTRAN ), wrap_error ) if ( size ( c_wrappers ) > 0 ) & call mpi_compiler_match ( LANG_C , c_wrappers , compiler , wrap ( LANG_C ), mpi ( LANG_C ), wrap_error ) if ( size ( cpp_wrappers ) > 0 ) & call mpi_compiler_match ( LANG_CXX , cpp_wrappers , compiler , wrap ( LANG_CXX ), mpi ( LANG_CXX ), wrap_error ) !> Find a Fortran wrapper for the current compiler if ( all ( wrap == 0 )) then call fatal_error ( error , 'no valid wrappers match current compiler, ' // compiler_name ( compiler )) return end if end subroutine wrapper_compiler_fit !> Check if a local MS-MPI SDK build is found logical function msmpi_init ( this , compiler , error ) result ( found ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error character ( len = :), allocatable :: incdir , windir , libdir , bindir , post , reall , msysdir type ( version_t ) :: ver , ver10 type ( string_t ) :: cpath , msys_path , runner_path logical :: msys2 !> Default: not found found = . false . if ( get_os_type () == OS_WINDOWS ) then ! to run MSMPI on Windows, is_minGW : if ( compiler % id == id_gcc ) then call compiler_get_version ( compiler , ver , msys2 , error ) if ( allocated ( error )) return endif is_minGW ! Check we're on a 64-bit environment if ( is_64bit_environment ()) then libdir = get_env ( 'MSMPI_LIB64' ) post = 'x64' else libdir = get_env ( 'MSMPI_LIB32' ) post = 'x86' !> Not working on 32-bit Windows yet call fatal_error ( error , 'MS-MPI error: this package requires 64-bit Windows environment' ) return end if ! Check that the runtime is installed bindir = \"\" call get_absolute_path ( get_env ( 'MSMPI_BIN' ), bindir , error ) if ( verbose ) print * , '+ %MSMPI_BIN%=' , bindir ! In some environments, variable %MSMPI_BIN% is missing (i.e. in GitHub Action images). ! Do a second attempt: search for the default location if ( len_trim ( bindir ) <= 0 . or . allocated ( error )) then if ( verbose ) print * , '+ %MSMPI_BIN% empty, searching C:\\Program Files\\Microsoft MPI\\Bin\\ ...' call get_absolute_path ( 'C:\\Program Files\\Microsoft MPI\\Bin\\mpiexec.exe' , bindir , error ) endif ! Third attempt for bash-style shell if ( len_trim ( bindir ) <= 0 . or . allocated ( error )) then if ( verbose ) print * , '+ %MSMPI_BIN% empty, searching /c/Program Files/Microsoft MPI/Bin/ ...' call get_absolute_path ( '/c/Program Files/Microsoft MPI/Bin/mpiexec.exe' , bindir , error ) endif ! Do a fourth attempt: search for mpiexec.exe in PATH location if ( len_trim ( bindir ) <= 0 . or . allocated ( error )) then if ( verbose ) print * , '+ C:\\Program Files\\Microsoft MPI\\Bin\\ not found. searching %PATH%...' call get_mpi_runner ( runner_path , verbose , error ) if (. not . allocated ( error )) then if ( verbose ) print * , '+ mpiexec found: ' , runner_path % s call find_command_location ( runner_path % s , bindir , verbose = verbose , error = error ) endif endif if ( allocated ( error )) then call fatal_error ( error , 'MS-MPI error: MS-MPI Runtime directory is missing. ' // & 'check environment variable %MSMPI_BIN% or that the folder is in %PATH%.' ) return end if ! Success! found = . true . ! Init ms-mpi call destroy ( this ) ! MSYS2 provides a pre-built static msmpi.dll.a library. Use that if possible use_prebuilt : if ( msys2 ) then ! MSYS executables are in %MSYS_ROOT%/bin call compiler_get_path ( compiler , cpath , error ) if ( allocated ( error )) return call get_absolute_path ( join_path ( cpath % s , '..' ), msys_path % s , error ) if ( allocated ( error )) return call get_absolute_path ( join_path ( msys_path % s , 'include' ), incdir , error ) if ( allocated ( error )) return call get_absolute_path ( join_path ( msys_path % s , 'lib' ), libdir , error ) if ( allocated ( error )) return if ( verbose ) print 1 , 'include' , incdir , exists ( incdir ) if ( verbose ) print 1 , 'library' , libdir , exists ( libdir ) ! Check that the necessary files exist call get_absolute_path ( join_path ( libdir , 'libmsmpi.dll.a' ), post , error ) if ( allocated ( error )) return if ( len_trim ( post ) <= 0 . or . . not . exists ( post )) then call fatal_error ( error , 'MS-MPI available through the MSYS2 system not found. ' // & 'Run ' // & 'or your system-specific version to install.' ) return end if ! Add dir cpath this % has_link_flags = . true . this % link_flags = string_t ( ' -L' // get_dos_path ( libdir , error )) this % has_link_libraries = . true . this % link_libs = [ string_t ( 'msmpi.dll' )] if ( allocated ( error )) return this % has_include_dirs = . true . this % incl_dirs = [ string_t ( get_dos_path ( incdir , error ))] if ( allocated ( error )) return else call fatal_error ( error , 'MS-MPI cannot work with non-MSYS2 GNU compilers yet' ) return ! Add dir path this % has_link_flags = . true . this % link_flags = string_t ( ' -L' // get_dos_path ( libdir , error )) this % has_link_libraries = . true . this % link_libs = [ string_t ( 'msmpi' ), string_t ( 'msmpifec' ), string_t ( 'msmpifmc' )] if ( allocated ( error )) return this % has_include_dirs = . true . this % incl_dirs = [ string_t ( get_dos_path ( incdir , error )), & string_t ( get_dos_path ( incdir // post , error ))] if ( allocated ( error )) return end if use_prebuilt !> Request Fortran implicit typing allocate ( this % fortran ) this % fortran % implicit_typing = . true . this % fortran % implicit_external = . true . ! gfortran>=10 is incompatible with the old-style mpif.h MS-MPI headers. ! If so, add flags to allow old-style BOZ constants in mpif.h allow_BOZ : if ( compiler % id == id_gcc ) then call new_version ( ver10 , '10.0.0' , error ) if ( allocated ( error )) return if ( ver >= ver10 ) then this % has_build_flags = . true . this % flags = string_t ( ' -fallow-invalid-boz' ) end if endif allow_BOZ !> Add default run command this % has_run_command = . true . this % run_command = string_t ( join_path ( get_dos_path ( bindir , error ), 'mpiexec.exe' ) // ' -np * ' ) else !> Not on Windows found = . false . end if 1 format ( 'MSMSPI ' , a , ' directory: PATH=' , a , ' EXISTS=' , l1 ) end function msmpi_init !> Check if we're under a WSL bash shell logical function wsl_shell () if ( get_os_type () == OS_WINDOWS ) then wsl_shell = exists ( '/proc/sys/fs/binfmt_misc/WSLInterop' ) else wsl_shell = . false . endif end function wsl_shell !> Find the location of a valid command subroutine find_command_location ( command , path , echo , verbose , error ) character ( * ), intent ( in ) :: command character ( len = :), allocatable , intent ( out ) :: path logical , optional , intent ( in ) :: echo , verbose type ( error_t ), allocatable , intent ( out ) :: error character (:), allocatable :: tmp_file , screen_output , line , fullpath , search_command integer :: stat , iunit , ire , length , try character ( * ), parameter :: search ( 2 ) = [ \"where \" , \"which \" ] if ( len_trim ( command ) <= 0 ) then call fatal_error ( error , 'empty command provided in find_command_location' ) return end if tmp_file = get_temp_filename () ! On Windows, we try both commands because we may be on WSL do try = merge ( 1 , 2 , get_os_type () == OS_WINDOWS ), 2 search_command = search ( try ) // command call run ( search_command , echo = echo , exitstat = stat , verbose = verbose , redirect = tmp_file ) if ( stat == 0 ) exit end do if ( stat /= 0 ) then call fatal_error ( error , 'find_command_location failed for ' // command ) return end if ! Only read first instance (first line) allocate ( character ( len = 0 ) :: screen_output ) open ( newunit = iunit , file = tmp_file , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit if ( len ( screen_output ) > 0 ) then screen_output = screen_output // new_line ( 'a' ) // line else screen_output = line endif end do ! Close and delete file close ( iunit , status = 'delete' ) else call fatal_error ( error , 'cannot read temporary file from successful find_command_location' ) return endif ! Only use the first instance length = index ( screen_output , new_line ( 'a' )) multiline : if ( length > 1 ) then fullpath = screen_output ( 1 : length - 1 ) else fullpath = screen_output endif multiline if ( len_trim ( fullpath ) < 1 ) then call fatal_error ( error , 'no paths found to command (' // command // ')' ) return end if ! Extract path only length = index ( fullpath , command , BACK = . true .) if ( length <= 0 ) then call fatal_error ( error , 'full path to command (' // command // ') does not include command name' ) return elseif ( length == 1 ) then ! Compiler is in the current folder path = '.' else path = fullpath ( 1 : length - 1 ) end if if ( allocated ( error )) return ! On Windows, be sure to return a path with no spaces if ( get_os_type () == OS_WINDOWS ) path = get_dos_path ( path , error ) if ( allocated ( error ) . or . . not . is_dir ( path )) then call fatal_error ( error , 'full path (' // path // ') to command (' // command // ') is not a directory' ) return end if end subroutine find_command_location !> Get MPI runner in $PATH subroutine get_mpi_runner ( command , verbose , error ) type ( string_t ), intent ( out ) :: command logical , intent ( in ) :: verbose type ( error_t ), allocatable , intent ( out ) :: error character ( * ), parameter :: try ( * ) = [ 'mpiexec ' , 'mpirun ' , 'mpiexec.exe' , 'mpirun.exe ' ] character (:), allocatable :: bindir integer :: itri logical :: success ! Try several commands do itri = 1 , size ( try ) call find_command_location ( trim ( try ( itri )), command % s , verbose = verbose , error = error ) if ( allocated ( error )) cycle ! Success! success = len_trim ( command % s ) > 0 if ( success ) then if ( verbose ) print * , '+ runner folder found: ' // command % s command % s = join_path ( command % s , trim ( try ( itri ))) return endif end do ! On windows, also search in %MSMPI_BIN% if ( get_os_type () == OS_WINDOWS ) then ! Check that the runtime is installed bindir = \"\" call get_absolute_path ( get_env ( 'MSMPI_BIN' ), bindir , error ) if ( verbose ) print * , '+ %MSMPI_BIN%=' , bindir ! In some environments, variable %MSMPI_BIN% is missing (i.e. in GitHub Action images). ! Do a second attempt: search for the default location if ( len_trim ( bindir ) <= 0 . or . allocated ( error )) then if ( verbose ) print * , '+ %MSMPI_BIN% empty, searching C:\\Program Files\\Microsoft MPI\\Bin\\ ...' call get_absolute_path ( 'C:\\Program Files\\Microsoft MPI\\Bin\\mpiexec.exe' , bindir , error ) endif if ( len_trim ( bindir ) > 0 . and . . not . allocated ( error )) then ! MSMPI_BIN directory found command % s = join_path ( bindir , 'mpiexec.exe' ) return endif endif ! No valid command found call fatal_error ( error , 'cannot find a valid mpi runner command' ) return end subroutine get_mpi_runner !> Return compiler path subroutine compiler_get_path ( self , path , error ) type ( compiler_t ), intent ( in ) :: self type ( string_t ), intent ( out ) :: path type ( error_t ), allocatable , intent ( out ) :: error call find_command_location ( self % fc , path % s , self % echo , self % verbose , error ) end subroutine compiler_get_path !> Return compiler version subroutine compiler_get_version ( self , version , is_msys2 , error ) type ( compiler_t ), intent ( in ) :: self type ( version_t ), intent ( out ) :: version logical , intent ( out ) :: is_msys2 type ( error_t ), allocatable , intent ( out ) :: error character (:), allocatable :: tmp_file , screen_output , line type ( string_t ) :: ver integer :: stat , iunit , ire , length is_msys2 = . false . select case ( self % id ) case ( id_gcc ) tmp_file = get_temp_filename () call run ( self % fc // \" --version \" , echo = self % echo , verbose = self % verbose , redirect = tmp_file , exitstat = stat ) if ( stat /= 0 ) then call fatal_error ( error , 'compiler_get_version failed for ' // self % fc ) return end if allocate ( character ( len = 0 ) :: screen_output ) open ( newunit = iunit , file = tmp_file , status = 'old' , iostat = stat ) if ( stat == 0 ) then do call getline ( iunit , line , stat ) if ( stat /= 0 ) exit screen_output = screen_output // ' ' // line // ' ' end do ! Close and delete file close ( iunit , status = 'delete' ) else call fatal_error ( error , 'cannot read temporary file from successful compiler_get_version' ) return endif ! Check if this gcc is from the MSYS2 project is_msys2 = index ( screen_output , 'MSYS2' ) > 0 ver = regex_version_from_text ( screen_output , self % fc // ' compiler' , error ) if ( allocated ( error )) return ! Extract version call new_version ( version , ver % s , error ) case default call fatal_error ( error , 'compiler_get_version not yet implemented for compiler ' // self % fc ) return end select end subroutine compiler_get_version !> Initialize an MPI metapackage from a valid wrapper command ('mpif90', etc...) subroutine init_mpi_from_wrappers ( this , compiler , mpilib , fort_wrapper , c_wrapper , cxx_wrapper , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler integer , intent ( in ) :: mpilib type ( string_t ), intent ( in ) :: fort_wrapper , c_wrapper , cxx_wrapper type ( error_t ), allocatable , intent ( out ) :: error type ( version_t ) :: version type ( error_t ), allocatable :: runner_error ! Cleanup structure call destroy ( this ) ! Get linking flags this % link_flags = mpi_wrapper_query ( mpilib , fort_wrapper , 'link' , verbose , error ) if ( allocated ( error )) return ! Remove useless/dangerous flags call filter_link_arguments ( compiler , this % link_flags ) this % has_link_flags = len_trim ( this % link_flags ) > 0 ! Request to use libs in arbitrary order if ( this % has_link_flags . and . compiler % is_gnu () . and . os_is_unix () . and . get_os_type () /= OS_MACOS ) then this % link_flags = string_t ( ' -Wl,--start-group ' // this % link_flags % s ) end if ! Add language-specific flags call set_language_flags ( compiler , mpilib , fort_wrapper , this % has_fortran_flags , this % fflags , verbose , error ) if ( allocated ( error )) return call set_language_flags ( compiler , mpilib , c_wrapper , this % has_c_flags , this % cflags , verbose , error ) if ( allocated ( error )) return call set_language_flags ( compiler , mpilib , cxx_wrapper , this % has_cxx_flags , this % cxxflags , verbose , error ) if ( allocated ( error )) return ! Get library version version = mpi_version_get ( mpilib , fort_wrapper , error ) if ( allocated ( error )) then return else allocate ( this % version , source = version ) end if !> Add default run command, if present this % run_command = mpi_wrapper_query ( mpilib , fort_wrapper , 'runner' , verbose , runner_error ) this % has_run_command = ( len_trim ( this % run_command ) > 0 ) . and . . not . allocated ( runner_error ) contains subroutine set_language_flags ( compiler , mpilib , wrapper , has_flags , flags , verbose , error ) type ( compiler_t ), intent ( in ) :: compiler integer , intent ( in ) :: mpilib type ( string_t ), intent ( in ) :: wrapper logical , intent ( inout ) :: has_flags type ( string_t ), intent ( inout ) :: flags logical , intent ( in ) :: verbose type ( error_t ), allocatable , intent ( out ) :: error ! Get build flags for each language if ( len_trim ( wrapper ) > 0 ) then flags = mpi_wrapper_query ( mpilib , wrapper , 'flags' , verbose , error ) if ( allocated ( error )) return has_flags = len_trim ( flags ) > 0 ! Add heading space flags = string_t ( ' ' // flags % s ) if ( verbose ) print * , '+ MPI language flags from wrapper <' , wrapper % s , '>: flags=' , flags % s call filter_build_arguments ( compiler , flags ) endif end subroutine set_language_flags end subroutine init_mpi_from_wrappers !> Match one of the available compiler wrappers with the current compiler subroutine mpi_compiler_match ( language , wrappers , compiler , which_one , mpilib , error ) integer , intent ( in ) :: language type ( string_t ), intent ( in ) :: wrappers (:) type ( compiler_t ), intent ( in ) :: compiler integer , intent ( out ) :: which_one , mpilib type ( error_t ), allocatable , intent ( out ) :: error integer :: i , same_vendor , vendor_mpilib type ( string_t ) :: screen character ( 128 ) :: msg_out type ( compiler_t ) :: mpi_compiler which_one = 0 same_vendor = 0 mpilib = MPI_TYPE_NONE if ( verbose ) print * , '+ Trying to match available ' , LANG_NAME ( language ), ' MPI wrappers to ' , compiler % fc , '...' do i = 1 , size ( wrappers ) mpilib = which_mpi_library ( wrappers ( i ), compiler , verbose = . false .) screen = mpi_wrapper_query ( mpilib , wrappers ( i ), 'compiler' , verbose = . false ., error = error ) if ( allocated ( error )) return if ( verbose ) print * , ' Wrapper ' , wrappers ( i )% s , ' lib=' , MPI_TYPE_NAME ( mpilib ), ' uses ' , screen % s select case ( language ) case ( LANG_FORTRAN ) ! Build compiler type. The ID is created based on the Fortran name call new_compiler ( mpi_compiler , screen % s , '' , '' , echo = . true ., verbose = . false .) ! Fortran match found! if ( mpi_compiler % id == compiler % id ) then which_one = i return end if case ( LANG_C ) ! For other languages, we can only hope that the name matches the expected one if ( screen % s == compiler % cc . or . screen % s == compiler % fc ) then which_one = i return end if case ( LANG_CXX ) if ( screen % s == compiler % cxx . or . screen % s == compiler % fc ) then which_one = i return end if end select ! Because the intel mpi library does not support llvm_ compiler wrappers yet, ! we must check for that manually if ( is_intel_classic_option ( language , same_vendor , screen , compiler , mpi_compiler )) then same_vendor = i vendor_mpilib = mpilib end if end do ! Intel compiler: if an exact match is not found, attempt closest wrapper if ( which_one == 0 . and . same_vendor > 0 ) then which_one = same_vendor mpilib = vendor_mpilib end if ! None of the available wrappers matched the current Fortran compiler write ( msg_out , 1 ) size ( wrappers ), compiler % fc call fatal_error ( error , trim ( msg_out )) 1 format ( ' None out of ' , i0 , ' valid MPI wrappers matches compiler ' , a ) end subroutine mpi_compiler_match !> Because the Intel mpi library does not support llvm_ compiler wrappers yet, !> we must save the Intel-classic option and later manually replace it logical function is_intel_classic_option ( language , same_vendor_ID , screen_out , compiler , mpi_compiler ) integer , intent ( in ) :: language , same_vendor_ID type ( string_t ), intent ( in ) :: screen_out type ( compiler_t ), intent ( in ) :: compiler , mpi_compiler if ( same_vendor_ID /= 0 ) then is_intel_classic_option = . false . else select case ( language ) case ( LANG_FORTRAN ) is_intel_classic_option = mpi_compiler % is_intel () . and . compiler % is_intel () case ( LANG_C ) is_intel_classic_option = screen_out % s == 'icc' . and . compiler % cc == 'icx' case ( LANG_CXX ) is_intel_classic_option = screen_out % s == 'icpc' . and . compiler % cc == 'icpx' end select end if end function is_intel_classic_option !> Return library version from the MPI wrapper command type ( version_t ) function mpi_version_get ( mpilib , wrapper , error ) integer , intent ( in ) :: mpilib type ( string_t ), intent ( in ) :: wrapper type ( error_t ), allocatable , intent ( out ) :: error type ( string_t ) :: version_line ! Get version string version_line = mpi_wrapper_query ( mpilib , wrapper , 'version' , error = error ) if ( allocated ( error )) return ! Wrap to object call new_version ( mpi_version_get , version_line % s , error ) end function mpi_version_get !> Return several mpi wrappers, and return subroutine mpi_wrappers ( compiler , fort_wrappers , c_wrappers , cpp_wrappers ) type ( compiler_t ), intent ( in ) :: compiler type ( string_t ), allocatable , intent ( out ) :: c_wrappers (:), cpp_wrappers (:), fort_wrappers (:) character ( len = :), allocatable :: mpi_root , intel_wrap type ( error_t ), allocatable :: error ! Attempt gathering MPI wrapper names from the environment variables c_wrappers = [ string_t ( get_env ( 'MPICC' , 'mpicc' ))] cpp_wrappers = [ string_t ( get_env ( 'MPICXX' , 'mpic++' ))] fort_wrappers = [ string_t ( get_env ( 'MPIFC' , 'mpifc' )),& string_t ( get_env ( 'MPIf90' , 'mpif90' )),& string_t ( get_env ( 'MPIf77' , 'mpif77' ))] if ( get_os_type () == OS_WINDOWS ) then c_wrappers = [ c_wrappers , string_t ( 'mpicc.bat' )] cpp_wrappers = [ cpp_wrappers , string_t ( 'mpicxx.bat' )] fort_wrappers = [ fort_wrappers , string_t ( 'mpifc.bat' )] endif ! Add compiler-specific wrappers compiler_specific : select case ( compiler % id ) case ( id_gcc , id_f95 ) c_wrappers = [ c_wrappers , string_t ( 'mpigcc' ), string_t ( 'mpgcc' )] cpp_wrappers = [ cpp_wrappers , string_t ( 'mpig++' ), string_t ( 'mpg++' )] fort_wrappers = [ fort_wrappers , string_t ( 'mpigfortran' ), string_t ( 'mpgfortran' ),& string_t ( 'mpig77' ), string_t ( 'mpg77' )] case ( id_intel_classic_windows , id_intel_llvm_windows , & id_intel_classic_nix , id_intel_classic_mac , id_intel_llvm_nix , id_intel_llvm_unknown ) c_wrappers = [ string_t ( get_env ( 'I_MPI_CC' , 'mpiicc' ))] cpp_wrappers = [ string_t ( get_env ( 'I_MPI_CXX' , 'mpiicpc' ))] fort_wrappers = [ string_t ( get_env ( 'I_MPI_F90' , 'mpiifort' ))] ! Also search MPI wrappers via the base MPI folder mpi_root = get_env ( 'I_MPI_ROOT' ) if ( mpi_root /= \"\" ) then mpi_root = join_path ( mpi_root , 'bin' ) intel_wrap = join_path ( mpi_root , 'mpiifort' ) if ( get_os_type () == OS_WINDOWS ) intel_wrap = get_dos_path ( intel_wrap , error ) if ( intel_wrap /= \"\" ) fort_wrappers = [ fort_wrappers , string_t ( intel_wrap )] intel_wrap = join_path ( mpi_root , 'mpiicc' ) if ( get_os_type () == OS_WINDOWS ) intel_wrap = get_dos_path ( intel_wrap , error ) if ( intel_wrap /= \"\" ) c_wrappers = [ c_wrappers , string_t ( intel_wrap )] intel_wrap = join_path ( mpi_root , 'mpiicpc' ) if ( get_os_type () == OS_WINDOWS ) intel_wrap = get_dos_path ( intel_wrap , error ) if ( intel_wrap /= \"\" ) cpp_wrappers = [ cpp_wrappers , string_t ( intel_wrap )] end if case ( id_pgi , id_nvhpc ) c_wrappers = [ c_wrappers , string_t ( 'mpipgicc' ), string_t ( 'mpgcc' )] cpp_wrappers = [ cpp_wrappers , string_t ( 'mpipgic++' )] fort_wrappers = [ fort_wrappers , string_t ( 'mpipgifort' ), string_t ( 'mpipgf90' )] case ( id_cray ) c_wrappers = [ c_wrappers , string_t ( 'cc' )] cpp_wrappers = [ cpp_wrappers , string_t ( 'CC' )] fort_wrappers = [ fort_wrappers , string_t ( 'ftn' )] end select compiler_specific call assert_mpi_wrappers ( fort_wrappers , compiler ) call assert_mpi_wrappers ( c_wrappers , compiler ) call assert_mpi_wrappers ( cpp_wrappers , compiler ) end subroutine mpi_wrappers !> Filter out invalid/unavailable mpi wrappers subroutine assert_mpi_wrappers ( wrappers , compiler , verbose ) type ( string_t ), allocatable , intent ( inout ) :: wrappers (:) type ( compiler_t ), intent ( in ) :: compiler logical , optional , intent ( in ) :: verbose integer :: i integer , allocatable :: works (:) allocate ( works ( size ( wrappers ))) do i = 1 , size ( wrappers ) if ( present ( verbose )) then if ( verbose ) print * , '+ MPI test wrapper <' , wrappers ( i )% s , '>' endif works ( i ) = which_mpi_library ( wrappers ( i ), compiler , verbose ) end do ! Filter out non-working wrappers wrappers = pack ( wrappers , works /= MPI_TYPE_NONE ) end subroutine assert_mpi_wrappers !> Get MPI library type from the wrapper command. Currently, only OpenMPI is supported integer function which_mpi_library ( wrapper , compiler , verbose ) type ( string_t ), intent ( in ) :: wrapper type ( compiler_t ), intent ( in ) :: compiler logical , intent ( in ), optional :: verbose logical :: is_mpi_wrapper integer :: stat ! Init as currently unsupported library which_mpi_library = MPI_TYPE_NONE if ( len_trim ( wrapper ) <= 0 ) return ! Run mpi wrapper first call run_wrapper ( wrapper , verbose = verbose , cmd_success = is_mpi_wrapper ) if ( is_mpi_wrapper ) then if ( compiler % is_intel ()) then which_mpi_library = MPI_TYPE_INTEL return end if ! Attempt to decipher which library this wrapper comes from. ! OpenMPI responds to '--showme' calls call run_wrapper ( wrapper ,[ string_t ( '--showme' )], verbose ,& exitcode = stat , cmd_success = is_mpi_wrapper ) if ( stat == 0 . and . is_mpi_wrapper ) then which_mpi_library = MPI_TYPE_OPENMPI return endif ! MPICH responds to '-show' calls call run_wrapper ( wrapper ,[ string_t ( '-show' )], verbose ,& exitcode = stat , cmd_success = is_mpi_wrapper ) if ( stat == 0 . and . is_mpi_wrapper ) then which_mpi_library = MPI_TYPE_MPICH return endif end if end function which_mpi_library !> Test if an MPI wrapper works type ( string_t ) function mpi_wrapper_query ( mpilib , wrapper , command , verbose , error ) result ( screen ) integer , intent ( in ) :: mpilib type ( string_t ), intent ( in ) :: wrapper character ( * ), intent ( in ) :: command logical , intent ( in ), optional :: verbose type ( error_t ), allocatable , intent ( out ) :: error logical :: success character (:), allocatable :: redirect_str , tokens (:), unsupported_msg type ( string_t ) :: cmdstr type ( compiler_t ) :: mpi_compiler integer :: stat , cmdstat , ire , length unsupported_msg = 'the MPI library of wrapper ' // wrapper % s // ' does not support task ' // trim ( command ) select case ( command ) ! Get MPI compiler name case ( 'compiler' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ); cmdstr = string_t ( '--showme:command' ) case ( MPI_TYPE_MPICH ); cmdstr = string_t ( '-compile-info' ) case ( MPI_TYPE_INTEL ); cmdstr = string_t ( '-show' ) case default call fatal_error ( error , unsupported_msg ) return end select call run_wrapper ( wrapper ,[ cmdstr ], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local ' // MPI_TYPE_NAME ( mpilib ) // & ' library wrapper does not support flag ' // cmdstr % s ) return end if ! Take out the first command from the whole line call remove_newline_characters ( screen ) call split ( screen % s , tokens , delimiters = ' ' ) screen % s = trim ( adjustl ( tokens ( 1 ))) ! Get a list of additional compiler flags case ( 'flags' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ); cmdstr = string_t ( '--showme:compile' ) case ( MPI_TYPE_MPICH ); cmdstr = string_t ( '-compile-info' ) case ( MPI_TYPE_INTEL ); cmdstr = string_t ( '-show' ) case default call fatal_error ( error , unsupported_msg ) return end select call run_wrapper ( wrapper ,[ cmdstr ], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local ' // MPI_TYPE_NAME ( mpilib ) // & ' library wrapper does not support flag ' // cmdstr % s ) return end if ! Post-process output select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) ! This library reports the compiler name only call remove_newline_characters ( screen ) case ( MPI_TYPE_MPICH , MPI_TYPE_INTEL ) ! These libraries report the full command including the compiler name. Remove it if so call remove_newline_characters ( screen ) call split ( screen % s , tokens ) ! Remove trailing compiler name screen % s = screen % s ( len_trim ( tokens ( 1 )) + 1 :) case default call fatal_error ( error , 'invalid MPI library type' ) return end select ! Get a list of additional linker flags case ( 'link' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ); cmdstr = string_t ( '--showme:link' ) case ( MPI_TYPE_MPICH ); cmdstr = string_t ( '-link-info' ) case ( MPI_TYPE_INTEL ); cmdstr = string_t ( '-show' ) case default call fatal_error ( error , unsupported_msg ) return end select call run_wrapper ( wrapper ,[ cmdstr ], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local ' // MPI_TYPE_NAME ( mpilib ) // & ' library wrapper does not support flag ' // cmdstr % s ) return end if select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) call remove_newline_characters ( screen ) case ( MPI_TYPE_MPICH , MPI_TYPE_INTEL ) ! MPICH reports the full command including the compiler name. Remove it if so call remove_newline_characters ( screen ) call split ( screen % s , tokens ) ! Remove trailing compiler name screen % s = screen % s ( len_trim ( tokens ( 1 )) + 1 :) case default call fatal_error ( error , unsupported_msg ) return end select ! Get a list of MPI library directories case ( 'link_dirs' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) ! --showme:command returns the build command of this wrapper call run_wrapper ( wrapper ,[ string_t ( '--showme:libdirs' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local OpenMPI library does not support --showme:libdirs' ) return end if case default call fatal_error ( error , unsupported_msg ) return end select ! Get a list of include directories for the MPI headers/modules case ( 'incl_dirs' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) ! --showme:command returns the build command of this wrapper call run_wrapper ( wrapper ,[ string_t ( '--showme:incdirs' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local OpenMPI library does not support --showme:incdirs' ) return end if case default call fatal_error ( error , unsupported_msg ) return end select call remove_newline_characters ( screen ) ! Retrieve library version case ( 'version' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI ) ! --showme:command returns the build command of this wrapper call run_wrapper ( wrapper ,[ string_t ( '--showme:version' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local OpenMPI library does not support --showme:version' ) return else call remove_newline_characters ( screen ) end if case ( MPI_TYPE_MPICH ) !> MPICH offers command \"mpichversion\" in the same system folder as the MPI wrappers. !> So, attempt to run that first cmdstr = string_t ( 'mpichversion' ) call run_wrapper ( cmdstr , verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) ! Second option: run mpich wrapper + \"-v\" if ( stat /= 0 . or . . not . success ) then call run_wrapper ( wrapper ,[ string_t ( '-v' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) call remove_newline_characters ( screen ) endif ! Third option: mpiexec --version if ( stat /= 0 . or . . not . success ) then cmdstr = string_t ( 'mpiexec --version' ) call run_wrapper ( cmdstr , verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) endif if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'cannot retrieve MPICH library version from ' ) return end if case ( MPI_TYPE_INTEL ) ! --showme:command returns the build command of this wrapper call run_wrapper ( wrapper ,[ string_t ( '-v' )], verbose = verbose , & exitcode = stat , cmd_success = success , screen_output = screen ) if ( stat /= 0 . or . . not . success ) then call syntax_error ( error , 'local INTEL MPI library does not support -v' ) return else call remove_newline_characters ( screen ) end if case default call fatal_error ( error , unsupported_msg ) return end select ! Extract version screen = regex_version_from_text ( screen % s , MPI_TYPE_NAME ( mpilib ) // ' library' , error ) if ( allocated ( error )) return ! Get path to the MPI runner command case ( 'runner' ) select case ( mpilib ) case ( MPI_TYPE_OPENMPI , MPI_TYPE_MPICH , MPI_TYPE_MSMPI , MPI_TYPE_INTEL ) call get_mpi_runner ( screen , verbose , error ) case default call fatal_error ( error , unsupported_msg ) return end select case default ; call fatal_error ( error , 'an invalid MPI wrapper command (' // command // & ') was invoked for wrapper <' // wrapper % s // '>.' ) return end select end function mpi_wrapper_query !> Check if input is a useful linker argument logical function is_link_argument ( compiler , string ) type ( compiler_t ), intent ( in ) :: compiler character ( * ), intent ( in ) :: string select case ( compiler % id ) case ( id_intel_classic_windows , id_intel_llvm_windows ) is_link_argument = string == '/link' & . or . str_begins_with_str ( string , '/LIBPATH' )& . or . str_ends_with ( string , '.lib' ) ! always .lib whether static or dynamic case default ! fix OpenMPI's Fortran wrapper bug (https://github.com/open-mpi/ompi/issues/11636) here is_link_argument = ( str_begins_with_str ( string , '-L' ) & . or . str_begins_with_str ( string , '-l' ) & . or . str_begins_with_str ( string , '-Xlinker' ) & . or . string == '-pthread' & . or . ( str_begins_with_str ( string , '-W' ) . and . & ( string /= '-Wall' ) . and . (. not . str_begins_with_str ( string , '-Werror' ))) ) & . and . . not . ( & ( get_os_type () == OS_MACOS . and . index ( string , '-commons,use_dylibs' ) > 0 ) ) end select end function is_link_argument !> From build, remove optimization and other unnecessary flags subroutine filter_build_arguments ( compiler , command ) type ( compiler_t ), intent ( in ) :: compiler type ( string_t ), intent ( inout ) :: command character ( len = :), allocatable :: tokens (:) integer :: i , n , re_i , re_l logical , allocatable :: keep (:) logical :: keep_next character ( len = :), allocatable :: module_flag , include_flag if ( len_trim ( command ) <= 0 ) return ! Split command into arguments tokens = shlex_split ( command % s ) module_flag = get_module_flag ( compiler , \"\" ) include_flag = get_include_flag ( compiler , \"\" ) n = size ( tokens ) allocate ( keep ( n ), source = . false .) keep_next = . false . do i = 1 , n if ( get_os_type () == OS_MACOS . and . index ( tokens ( i ), '-commons,use_dylibs' ) > 0 ) then keep ( i ) = . false . keep_next = . false . elseif ( str_begins_with_str ( tokens ( i ), '-D' ) . or . & str_begins_with_str ( tokens ( i ), '-f' ) . or . & str_begins_with_str ( tokens ( i ), '-I' ) . or . & str_begins_with_str ( tokens ( i ), module_flag ) . or . & str_begins_with_str ( tokens ( i ), include_flag ) . or . & tokens ( i ) == '-pthread' . or . & ( str_begins_with_str ( tokens ( i ), '-W' ) . and . tokens ( i ) /= '-Wall' . and . . not . str_begins_with_str ( tokens ( i ), '-Werror' )) & ) then keep ( i ) = . true . if ( tokens ( i ) == module_flag . or . tokens ( i ) == include_flag . or . tokens ( i ) == '-I' ) keep_next = . true . elseif ( keep_next ) then keep ( i ) = . true . keep_next = . false . end if end do ! Backfill command = string_t ( \"\" ) do i = 1 , n if (. not . keep ( i )) cycle command % s = command % s // ' ' // trim ( tokens ( i )) end do end subroutine filter_build_arguments !> From the linker flags, remove optimization and other unnecessary flags subroutine filter_link_arguments ( compiler , command ) type ( compiler_t ), intent ( in ) :: compiler type ( string_t ), intent ( inout ) :: command character ( len = :), allocatable :: tokens (:) integer :: i , n logical , allocatable :: keep (:) logical :: keep_next if ( len_trim ( command ) <= 0 ) return ! Split command into arguments tokens = shlex_split ( command % s ) n = size ( tokens ) allocate ( keep ( n ), source = . false .) keep_next = . false . do i = 1 , n if ( is_link_argument ( compiler , tokens ( i ))) then keep ( i ) = . true . if ( tokens ( i ) == '-L' . or . tokens ( i ) == '-Xlinker' ) keep_next = . true . elseif ( keep_next ) then keep ( i ) = . true . keep_next = . false . end if end do ! Backfill command = string_t ( \"\" ) do i = 1 , n if (. not . keep ( i )) cycle command % s = command % s // ' ' // trim ( tokens ( i )) end do end subroutine filter_link_arguments !> Given a library name and folder, find extension and prefix subroutine lib_get_trailing ( lib_name , lib_dir , prefix , suffix , found ) character ( * ), intent ( in ) :: lib_name , lib_dir character (:), allocatable , intent ( out ) :: prefix , suffix logical , intent ( out ) :: found character ( * ), parameter :: extensions ( * ) = [ character ( 11 ) :: '.dll.a' , '.a' , '.dylib' , '.dll' ] logical :: is_file character (:), allocatable :: noext , tokens (:), path integer :: l , k ! Extract name with no extension call split ( lib_name , tokens , '.' ) noext = trim ( tokens ( 1 )) ! Get library extension: find file name: NAME.a, NAME.dll.a, NAME.dylib, libNAME.a, etc. found = . false . suffix = \"\" prefix = \"\" with_pref : do l = 1 , 2 if ( l == 2 ) then prefix = \"lib\" else prefix = \"\" end if find_ext : do k = 1 , size ( extensions ) path = join_path ( lib_dir , prefix // noext // trim ( extensions ( k ))) inquire ( file = path , exist = is_file ) if ( is_file ) then suffix = trim ( extensions ( k )) found = . true . exit with_pref end if end do find_ext end do with_pref if (. not . found ) then prefix = \"\" suffix = \"\" end if end subroutine lib_get_trailing !> Initialize HDF5 metapackage for the current system subroutine init_hdf5 ( this , compiler , error ) class ( metapackage_t ), intent ( inout ) :: this type ( compiler_t ), intent ( in ) :: compiler type ( error_t ), allocatable , intent ( out ) :: error character ( * ), parameter :: find_hl ( * ) = & [ character ( 11 ) :: '_hl_fortran' , 'hl_fortran' , '_fortran' , '_hl' ] character ( * ), parameter :: candidates ( * ) = & [ character ( 15 ) :: 'hdf5_hl_fortran' , 'hdf5-hl-fortran' , 'hdf5_fortran' , 'hdf5-fortran' ,& 'hdf5_hl' , 'hdf5' , 'hdf5-serial' ] integer :: i , j , k , l logical :: s , found_hl ( size ( find_hl )), found type ( string_t ) :: log , this_lib type ( string_t ), allocatable :: libs (:), flags (:), modules (:), non_fortran (:) character ( len = :), allocatable :: name , module_flag , include_flag , libdir , ext , pref module_flag = get_module_flag ( compiler , \"\" ) include_flag = get_include_flag ( compiler , \"\" ) !> Cleanup call destroy ( this ) allocate ( this % link_libs ( 0 ), this % incl_dirs ( 0 ), this % external_modules ( 0 ), non_fortran ( 0 )) this % link_flags = string_t ( \"\" ) this % flags = string_t ( \"\" ) !> Assert pkg-config is installed if (. not . assert_pkg_config ()) then call fatal_error ( error , 'hdf5 metapackage requires pkg-config' ) return end if !> Find pkg-config package file by priority name = 'NOT_FOUND' find_package : do i = 1 , size ( candidates ) if ( pkgcfg_has_package ( trim ( candidates ( i )))) then name = trim ( candidates ( i )) exit find_package end if end do find_package !> some distros put hdf5-1.2.3.pc with version number in .pc filename. if ( name == 'NOT_FOUND' ) then modules = pkgcfg_list_all ( error ) find_global_package : do i = 1 , size ( modules ) if ( str_begins_with_str ( modules ( i )% s , 'hdf5' )) then name = modules ( i )% s exit find_global_package end if end do find_global_package end if if ( name == 'NOT_FOUND' ) then call fatal_error ( error , 'pkg-config could not find a suitable hdf5 package.' ) return end if !> Get version log = pkgcfg_get_version ( name , error ) if ( allocated ( error )) return allocate ( this % version ) call new_version ( this % version , log % s , error ) if ( allocated ( error )) return !> Get libraries libs = pkgcfg_get_libs ( name , error ) if ( allocated ( error )) return libdir = \"\" do i = 1 , size ( libs ) if ( str_begins_with_str ( libs ( i )% s , '-l' )) then this % has_link_libraries = . true . this % link_libs = [ this % link_libs , string_t ( libs ( i )% s ( 3 :))] else ! -L and others: concatenate this % has_link_flags = . true . this % link_flags = string_t ( trim ( this % link_flags % s ) // ' ' // libs ( i )% s ) ! Also save library dir if ( str_begins_with_str ( libs ( i )% s , '-L' )) then libdir = libs ( i )% s ( 3 :) elseif ( str_begins_with_str ( libs ( i )% s , '/LIBPATH' )) then libdir = libs ( i )% s ( 9 :) endif end if end do ! Some pkg-config hdf5.pc (e.g. Ubuntu) don't include the commonly-used HL HDF5 libraries, ! so let's add them if they exist if ( len_trim ( libdir ) > 0 ) then do i = 1 , size ( this % link_libs ) found_hl = . false . if (. not . str_ends_with ( this % link_libs ( i )% s , find_hl )) then ! Extract name with no extension call lib_get_trailing ( this % link_libs ( i )% s , libdir , pref , ext , found ) ! Search how many versions with the Fortran endings there are finals : do k = 1 , size ( find_hl ) do j = 1 , size ( this % link_libs ) if ( str_begins_with_str ( this % link_libs ( j )% s , this % link_libs ( i )% s ) . and . & str_ends_with ( this % link_libs ( j )% s , trim ( find_hl ( k )))) then found_hl ( k ) = . true . cycle finals end if end do end do finals ! For each of the missing ones, if there is a file, add it add_missing : do k = 1 , size ( find_hl ) if ( found_hl ( k )) cycle add_missing ! Build file name this_lib % s = join_path ( libdir , pref // this % link_libs ( i )% s // trim ( find_hl ( k )) // ext ) inquire ( file = this_lib % s , exist = found ) ! File exists, but it is not linked against if ( found ) this % link_libs = [ this % link_libs , & string_t ( this % link_libs ( i )% s // trim ( find_hl ( k )))] end do add_missing end if end do endif !> Get compiler flags flags = pkgcfg_get_build_flags ( name ,. true ., error ) if ( allocated ( error )) return do i = 1 , size ( flags ) if ( str_begins_with_str ( flags ( i )% s , include_flag )) then this % has_include_dirs = . true . this % incl_dirs = [ this % incl_dirs , string_t ( flags ( i )% s ( len ( include_flag ) + 1 :))] else this % has_build_flags = . true . this % flags = string_t ( trim ( this % flags % s ) // ' ' // flags ( i )% s ) end if end do !> Add HDF5 modules as external this % has_external_modules = . true . this % external_modules = [ string_t ( 'h5a' ), & string_t ( 'h5d' ), & string_t ( 'h5es' ), & string_t ( 'h5e' ), & string_t ( 'h5f' ), & string_t ( 'h5g' ), & string_t ( 'h5i' ), & string_t ( 'h5l' ), & string_t ( 'h5o' ), & string_t ( 'h5p' ), & string_t ( 'h5r' ), & string_t ( 'h5s' ), & string_t ( 'h5t' ), & string_t ( 'h5vl' ), & string_t ( 'h5z' ), & string_t ( 'h5lib' ), & string_t ( 'h5global' ), & string_t ( 'h5_gen' ), & string_t ( 'h5fortkit' ), & string_t ( 'hdf5' )] end subroutine init_hdf5 end module fpm_meta","tags":"","loc":"sourcefile/fpm_meta.f90.html"},{"title":"fpm_strings.f90 – Fortran-lang/fpm","text":"Source Code !> This module defines general procedures for **string operations** for both CHARACTER and !! TYPE(STRING_T) variables ! !>## general routines for performing __string operations__ !! !!### Types !! - **TYPE(STRING_T)** define a type to contain strings of variable length !!### Type Conversions !! - [[F_STRING]] return Fortran **CHARACTER** variable when given a C-like array of !! single characters terminated with a C_NULL_CHAR **CHARACTER** !! - [[STR]] Converts **INTEGER** or** LOGICAL** to **CHARACTER** string !!### Case !! - [[LOWER]] Changes a string to lowercase over optional specified column range !!### Parsing and joining !! - [[SPLIT]] parse string on delimiter characters and store tokens into an allocatable array !! - [[SPLIT_FIRST_LAST]] Computes the first and last indices of tokens in input string, delimited by the characters in set, !! and stores them into first and last output arrays. !! - [[STRING_CAT]] Concatenate an array of **type(string_t)** into a single **CHARACTER** variable !! - [[JOIN]] append an array of **CHARACTER** variables into a single **CHARACTER** variable !!### Testing !! - [[STR_ENDS_WITH]] test if a **CHARACTER** string or array ends with a specified suffix !! - [[STRING_ARRAY_CONTAINS]] Check if array of **TYPE(STRING_T)** matches a particular **CHARACTER** string !! - **OPERATOR(.IN.)** Check if array of **TYPE(STRING_T)** matches a particular **CHARACTER** string !! - [[GLOB]] function compares text strings, one of which can have wildcards ('*' or '?'). !! - [[IS_FORTRAN_NAME]] determine whether a string is an acceptable Fortran entity name !! - [[TO_FORTRAN_NAME]] replace allowed special but unusuable characters in names with underscore !!### Whitespace !! - [[NOTABS]] subroutine to expand tab characters assuming a tab space every eight characters !! - [[DILATE]] function to expand tab characters assuming a tab space every eight characters !! - [[LEN_TRIM]] Determine total trimmed length of **STRING_T** array !!### Miscellaneous !! - [[FNV_1A]] Hash a **CHARACTER(*)** string of default kind or a **TYPE(STRING_T)** array !! - [[REPLACE]] Returns string with characters in charset replaced with target_char. !! - [[RESIZE]] increase the size of a **TYPE(STRING_T)** array by N elements !! module fpm_strings use iso_fortran_env , only : int64 use , intrinsic :: iso_fortran_env , only : stdin => input_unit , & & stdout => output_unit , & & stderr => error_unit use iso_c_binding , only : c_char , c_ptr , c_int , c_null_char , c_associated , c_f_pointer , c_size_t implicit none private public :: f_string , lower , upper , split , split_first_last , str_ends_with , string_t , str_begins_with_str public :: to_fortran_name , is_fortran_name public :: string_array_contains , string_cat , len_trim , operator (. in .), fnv_1a public :: replace , resize , str , join , glob public :: notabs , dilate , remove_newline_characters , remove_characters_in_set public :: operator ( == ) !> Module naming public :: is_valid_module_name , is_valid_module_prefix , & has_valid_custom_prefix , has_valid_standard_prefix , & module_prefix_template , module_prefix_type type string_t character ( len = :), allocatable :: s end type interface len_trim module procedure :: string_len_trim module procedure :: strings_len_trim end interface len_trim interface resize module procedure :: resize_string end interface interface operator (. in .) module procedure string_array_contains end interface interface fnv_1a procedure :: fnv_1a_char procedure :: fnv_1a_string_t end interface fnv_1a interface str_ends_with procedure :: str_ends_with_str procedure :: str_ends_with_any procedure :: str_ends_with_any_string end interface str_ends_with interface str module procedure str_int , str_int64 , str_logical end interface interface string_t module procedure new_string_t end interface string_t interface f_string module procedure f_string , f_string_cptr , f_string_cptr_n end interface f_string interface operator ( == ) module procedure string_is_same module procedure string_arrays_same end interface contains !> test if a CHARACTER string ends with a specified suffix pure logical function str_ends_with_str ( s , e ) result ( r ) character ( * ), intent ( in ) :: s , e integer :: n1 , n2 n1 = len ( s ) - len ( e ) + 1 n2 = len ( s ) if ( n1 < 1 ) then r = . false . else r = ( s ( n1 : n2 ) == e ) end if end function str_ends_with_str !> test if a CHARACTER string ends with any of an array of suffixs pure logical function str_ends_with_any ( s , e ) result ( r ) character ( * ), intent ( in ) :: s character ( * ), intent ( in ) :: e (:) integer :: i r = . true . do i = 1 , size ( e ) if ( str_ends_with ( s , trim ( e ( i )))) return end do r = . false . end function str_ends_with_any !> Test if a CHARACTER string ends with any of an array of string suffixs pure logical function str_ends_with_any_string ( s , e ) result ( r ) character ( * ), intent ( in ) :: s type ( string_t ), intent ( in ) :: e (:) integer :: i r = . true . do i = 1 , size ( e ) if ( str_ends_with ( s , trim ( e ( i )% s ))) return end do r = . false . end function str_ends_with_any_string !> test if a CHARACTER string begins with a specified prefix pure logical function str_begins_with_str ( s , e , case_sensitive ) result ( r ) character ( * ), intent ( in ) :: s , e logical , optional , intent ( in ) :: case_sensitive ! Default option: case sensitive integer :: n1 , n2 logical :: lower_case ! Check if case sensitive if ( present ( case_sensitive )) then lower_case = . not . case_sensitive else lower_case = . false . end if n1 = 1 n2 = 1 + len ( e ) - 1 if ( n2 > len ( s )) then r = . false . elseif ( lower_case ) then r = lower ( s ( n1 : n2 )) == lower ( e ) else r = ( s ( n1 : n2 ) == e ) end if end function str_begins_with_str !> return Fortran character variable when given a C-like array of !! single characters terminated with a C_NULL_CHAR character function f_string ( c_string ) use iso_c_binding character ( len = 1 ), intent ( in ) :: c_string (:) character (:), allocatable :: f_string integer :: i , n i = 0 do while ( c_string ( i + 1 ) /= C_NULL_CHAR ) i = i + 1 end do n = i allocate ( character ( n ) :: f_string ) do i = 1 , n f_string ( i : i ) = c_string ( i ) end do end function f_string !> return Fortran character variable when given a null-terminated c_ptr function f_string_cptr ( cptr ) result ( s ) type ( c_ptr ), intent ( in ), value :: cptr character ( len = :, kind = c_char ), allocatable :: s interface function c_strlen ( s ) result ( r ) bind ( c , name = \"strlen\" ) import c_size_t , c_ptr type ( c_ptr ), intent ( in ), value :: s integer ( kind = c_size_t ) :: r end function end interface s = f_string_cptr_n ( cptr , c_strlen ( cptr )) end function !> return Fortran character variable when given a null-terminated c_ptr and its length function f_string_cptr_n ( cptr , n ) result ( s ) type ( c_ptr ), intent ( in ), value :: cptr integer ( kind = c_size_t ), intent ( in ) :: n character ( len = n , kind = c_char ) :: s character ( len = n , kind = c_char ), pointer :: sptr call c_f_pointer ( cptr , sptr ) s = sptr end function !> Hash a character(*) string of default kind pure function fnv_1a_char ( input , seed ) result ( hash ) character ( * ), intent ( in ) :: input integer ( int64 ), intent ( in ), optional :: seed integer ( int64 ) :: hash integer :: i integer ( int64 ), parameter :: FNV_OFFSET_32 = 2166136261_int64 integer ( int64 ), parameter :: FNV_PRIME_32 = 16777619_int64 if ( present ( seed )) then hash = seed else hash = FNV_OFFSET_32 end if do i = 1 , len ( input ) hash = ieor ( hash , iachar ( input ( i : i ), int64 )) * FNV_PRIME_32 end do end function fnv_1a_char !> Hash a string_t array of default kind pure function fnv_1a_string_t ( input , seed ) result ( hash ) type ( string_t ), intent ( in ) :: input (:) integer ( int64 ), intent ( in ), optional :: seed integer ( int64 ) :: hash integer :: i hash = fnv_1a ( input ( 1 )% s , seed ) do i = 2 , size ( input ) hash = fnv_1a ( input ( i )% s , hash ) end do end function fnv_1a_string_t !>Author: John S. Urban !!License: Public Domain !! Changes a string to lowercase over optional specified column range elemental pure function lower ( str , begin , end ) result ( string ) character ( * ), intent ( In ) :: str character ( len ( str )) :: string integer , intent ( in ), optional :: begin , end integer :: i integer :: ibegin , iend string = str ibegin = 1 if ( present ( begin )) then ibegin = max ( ibegin , begin ) endif iend = len_trim ( str ) if ( present ( end )) then iend = min ( iend , end ) endif do i = ibegin , iend ! step thru each letter in the string in specified range select case ( str ( i : i )) case ( 'A' : 'Z' ) string ( i : i ) = char ( iachar ( str ( i : i )) + 32 ) ! change letter to miniscule case default end select end do end function lower !!License: Public Domain !! Changes a string to upprtcase over optional specified column range elemental pure function upper ( str , begin , end ) result ( string ) character ( * ), intent ( In ) :: str character ( len ( str )) :: string integer , intent ( in ), optional :: begin , end integer :: i integer :: ibegin , iend string = str ibegin = 1 if ( present ( begin )) then ibegin = max ( ibegin , begin ) endif iend = len_trim ( str ) if ( present ( end )) then iend = min ( iend , end ) endif do i = ibegin , iend ! step thru each letter in the string in specified range select case ( str ( i : i )) case ( 'a' : 'z' ) string ( i : i ) = char ( iachar ( str ( i : i )) - 32 ) ! change letter to capitalized case default end select end do end function upper !> Helper function to generate a new string_t instance !> (Required due to the allocatable component) function new_string_t ( s ) result ( string ) character ( * ), intent ( in ) :: s type ( string_t ) :: string string % s = s end function new_string_t !> Check if array of TYPE(STRING_T) matches a particular CHARACTER string !! logical function string_array_contains ( search_string , array ) character ( * ), intent ( in ) :: search_string type ( string_t ), intent ( in ) :: array (:) integer :: i string_array_contains = any ([( array ( i )% s == search_string , & i = 1 , size ( array ))]) end function string_array_contains !> Concatenate an array of type(string_t) into !> a single CHARACTER variable function string_cat ( strings , delim ) result ( cat ) type ( string_t ), intent ( in ) :: strings (:) character ( * ), intent ( in ), optional :: delim character (:), allocatable :: cat integer :: i character (:), allocatable :: delim_str if ( size ( strings ) < 1 ) then cat = '' return end if if ( present ( delim )) then delim_str = delim else delim_str = '' end if cat = strings ( 1 )% s do i = 2 , size ( strings ) cat = cat // delim_str // strings ( i )% s end do end function string_cat !> Determine total trimmed length of `string_t` array pure function strings_len_trim ( strings ) result ( n ) type ( string_t ), intent ( in ) :: strings (:) integer :: i , n n = 0 do i = 1 , size ( strings ) n = n + len_trim ( strings ( i )% s ) end do end function strings_len_trim !> Determine total trimmed length of `string_t` array elemental integer function string_len_trim ( string ) result ( n ) type ( string_t ), intent ( in ) :: string if ( allocated ( string % s )) then n = len_trim ( string % s ) else n = 0 end if end function string_len_trim !>Author: John S. Urban !!License: Public Domain !! parse string on delimiter characters and store tokens into an allocatable array subroutine split ( input_line , array , delimiters , order , nulls ) !! given a line of structure \" par1 par2 par3 ... parn \" store each par(n) into a separate variable in array. !! !! * by default adjacent delimiters in the input string do not create an empty string in the output array !! * no quoting of delimiters is supported character ( len =* ), intent ( in ) :: input_line !! input string to tokenize character ( len =* ), optional , intent ( in ) :: delimiters !! list of delimiter characters character ( len =* ), optional , intent ( in ) :: order !! order of output array sequential|[reverse|right] character ( len =* ), optional , intent ( in ) :: nulls !! return strings composed of delimiters or not ignore|return|ignoreend character ( len = :), allocatable , intent ( out ) :: array (:) !! output array of tokens integer :: n ! max number of strings INPUT_LINE could split into if all delimiter integer , allocatable :: ibegin (:) ! positions in input string where tokens start integer , allocatable :: iterm (:) ! positions in input string where tokens end character ( len = :), allocatable :: dlim ! string containing delimiter characters character ( len = :), allocatable :: ordr ! string containing order keyword character ( len = :), allocatable :: nlls ! string containing nulls keyword integer :: ii , iiii ! loop parameters used to control print order integer :: icount ! number of tokens found integer :: ilen ! length of input string with trailing spaces trimmed integer :: i10 , i20 , i30 ! loop counters integer :: icol ! pointer into input string as it is being parsed integer :: idlim ! number of delimiter characters integer :: ifound ! where next delimiter character is found in remaining input string data integer :: inotnull ! count strings not composed of delimiters integer :: ireturn ! number of tokens returned integer :: imax ! length of longest token ! decide on value for optional DELIMITERS parameter if ( present ( delimiters )) then ! optional delimiter list was present if ( delimiters /= '' ) then ! if DELIMITERS was specified and not null use it dlim = delimiters else ! DELIMITERS was specified on call as empty string dlim = ' ' // char ( 9 ) // char ( 10 ) // char ( 11 ) // char ( 12 ) // char ( 13 ) // char ( 0 ) ! use default delimiter when not specified endif else ! no delimiter value was specified dlim = ' ' // char ( 9 ) // char ( 10 ) // char ( 11 ) // char ( 12 ) // char ( 13 ) // char ( 0 ) ! use default delimiter when not specified endif idlim = len ( dlim ) ! dlim a lot of blanks on some machines if dlim is a big string if ( present ( order )) then ; ordr = lower ( adjustl ( order )); else ; ordr = 'sequential' ; endif ! decide on value for optional ORDER parameter if ( present ( nulls )) then ; nlls = lower ( adjustl ( nulls )); else ; nlls = 'ignore' ; endif ! optional parameter n = len ( input_line ) + 1 ! max number of strings INPUT_LINE could split into if all delimiter allocate ( ibegin ( n )) ! allocate enough space to hold starting location of tokens if string all tokens allocate ( iterm ( n )) ! allocate enough space to hold ending location of tokens if string all tokens ibegin (:) = 1 iterm (:) = 1 ilen = len ( input_line ) ! ILEN is the column position of the last non-blank character icount = 0 ! how many tokens found inotnull = 0 ! how many tokens found not composed of delimiters imax = 0 ! length of longest token found select case ( ilen ) case ( 0 ) ! command was totally blank case default ! there is at least one non-delimiter in INPUT_LINE if get here icol = 1 ! initialize pointer into input line INFINITE : do i30 = 1 , ilen , 1 ! store into each array element ibegin ( i30 ) = icol ! assume start new token on the character if ( index ( dlim ( 1 : idlim ), input_line ( icol : icol )) == 0 ) then ! if current character is not a delimiter iterm ( i30 ) = ilen ! initially assume no more tokens do i10 = 1 , idlim ! search for next delimiter ifound = index ( input_line ( ibegin ( i30 ): ilen ), dlim ( i10 : i10 )) IF ( ifound > 0 ) then iterm ( i30 ) = min ( iterm ( i30 ), ifound + ibegin ( i30 ) - 2 ) endif enddo icol = iterm ( i30 ) + 2 ! next place to look as found end of this token inotnull = inotnull + 1 ! increment count of number of tokens not composed of delimiters else ! character is a delimiter for a null string iterm ( i30 ) = icol - 1 ! record assumed end of string. Will be less than beginning icol = icol + 1 ! advance pointer into input string endif imax = max ( imax , iterm ( i30 ) - ibegin ( i30 ) + 1 ) icount = i30 ! increment count of number of tokens found if ( icol > ilen ) then ! no text left exit INFINITE endif enddo INFINITE end select select case ( trim ( adjustl ( nlls ))) case ( 'ignore' , '' , 'ignoreend' ) ireturn = inotnull case default ireturn = icount end select allocate ( character ( len = imax ) :: array ( ireturn )) ! allocate the array to return !allocate(array(ireturn)) ! allocate the array to turn select case ( trim ( adjustl ( ordr ))) ! decide which order to store tokens case ( 'reverse' , 'right' ) ; ii = ireturn ; iiii =- 1 ! last to first case default ; ii = 1 ; iiii = 1 ! first to last end select do i20 = 1 , icount ! fill the array with the tokens that were found if ( iterm ( i20 ) < ibegin ( i20 )) then select case ( trim ( adjustl ( nlls ))) case ( 'ignore' , '' , 'ignoreend' ) case default array ( ii ) = ' ' ii = ii + iiii end select else array ( ii ) = input_line ( ibegin ( i20 ): iterm ( i20 )) ii = ii + iiii endif enddo end subroutine split !! Author: Milan Curcic !! Computes the first and last indices of tokens in input string, delimited !! by the characters in set, and stores them into first and last output !! arrays. pure subroutine split_first_last ( string , set , first , last ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: set integer , allocatable , intent ( out ) :: first (:) integer , allocatable , intent ( out ) :: last (:) integer , dimension ( len ( string ) + 1 ) :: istart , iend integer :: p , n , slen slen = len ( string ) n = 0 if ( slen > 0 ) then p = 0 do while ( p < slen ) n = n + 1 istart ( n ) = min ( p + 1 , slen ) call split_pos ( string , set , p ) iend ( n ) = p - 1 end do end if first = istart (: n ) last = iend (: n ) end subroutine split_first_last !! Author: Milan Curcic !! If back is absent, computes the leftmost token delimiter in string whose !! position is > pos. If back is present and true, computes the rightmost !! token delimiter in string whose position is < pos. The result is stored !! in pos. pure subroutine split_pos ( string , set , pos , back ) character ( * ), intent ( in ) :: string character ( * ), intent ( in ) :: set integer , intent ( in out ) :: pos logical , intent ( in ), optional :: back logical :: backward integer :: result_pos , bound if ( len ( string ) == 0 ) then pos = 1 return end if !TODO use optval when implemented in stdlib !backward = optval(back, .false.) backward = . false . if ( present ( back )) backward = back if ( backward ) then bound = min ( len ( string ), max ( pos - 1 , 0 )) result_pos = scan ( string (: bound ), set , back = . true .) else result_pos = scan ( string ( min ( pos + 1 , len ( string )):), set ) + pos if ( result_pos < pos + 1 ) result_pos = len ( string ) + 1 end if pos = result_pos end subroutine split_pos !> Returns string with characters in charset replaced with target_char. pure function replace ( string , charset , target_char ) result ( res ) character ( * ), intent ( in ) :: string character , intent ( in ) :: charset (:), target_char character ( len ( string )) :: res integer :: n res = string do n = 1 , len ( string ) if ( any ( string ( n : n ) == charset )) then res ( n : n ) = target_char end if end do end function replace !> increase the size of a TYPE(STRING_T) array by N elements subroutine resize_string ( list , n ) !> Instance of the array to be resized type ( string_t ), allocatable , intent ( inout ) :: list (:) !> Dimension of the final array size integer , intent ( in ), optional :: n type ( string_t ), allocatable :: tmp (:) integer :: this_size , new_size , i integer , parameter :: initial_size = 16 if ( allocated ( list )) then this_size = size ( list , 1 ) call move_alloc ( list , tmp ) else this_size = initial_size end if if ( present ( n )) then new_size = n else new_size = this_size + this_size / 2 + 1 end if allocate ( list ( new_size )) if ( allocated ( tmp )) then this_size = min ( size ( tmp , 1 ), size ( list , 1 )) do i = 1 , this_size call move_alloc ( tmp ( i )% s , list ( i )% s ) end do deallocate ( tmp ) end if end subroutine resize_string !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!##NAME !! join(3f) - [M_strings:EDITING] append CHARACTER variable array into !! a single CHARACTER variable with specified separator !! (LICENSE:PD) !! !!##SYNOPSIS !! !! pure function join(str,sep,trm,left,right,start,end) result (string) !! !! character(len=*),intent(in) :: str(:) !! character(len=*),intent(in),optional :: sep !! logical,intent(in),optional :: trm !! character(len=*),intent(in),optional :: right !! character(len=*),intent(in),optional :: left !! character(len=*),intent(in),optional :: start !! character(len=*),intent(in),optional :: end !! character(len=:),allocatable :: string !! !!##DESCRIPTION !! JOIN(3f) appends the elements of a CHARACTER array into a single !! CHARACTER variable, with elements 1 to N joined from left to right. !! By default each element is trimmed of trailing spaces and the !! default separator is a null string. !! !!##OPTIONS !! STR(:) array of CHARACTER variables to be joined !! SEP separator string to place between each variable. defaults !! to a null string. !! LEFT string to place at left of each element !! RIGHT string to place at right of each element !! START prefix string !! END suffix string !! TRM option to trim each element of STR of trailing !! spaces. Defaults to .TRUE. !! !!##RESULT !! STRING CHARACTER variable composed of all of the elements of STR() !! appended together with the optional separator SEP placed !! between the elements. !! !!##EXAMPLE !! !! Sample program: !! !! program demo_join !! use M_strings, only: join !! implicit none !! character(len=:),allocatable :: s(:) !! character(len=:),allocatable :: out !! integer :: i !! s=[character(len=10) :: 'United',' we',' stand,', & !! & ' divided',' we fall.'] !! out=join(s) !! write(*,'(a)') out !! write(*,'(a)') join(s,trm=.false.) !! write(*,'(a)') (join(s,trm=.false.,sep='|'),i=1,3) !! write(*,'(a)') join(s,sep='<>') !! write(*,'(a)') join(s,sep=';',left='[',right=']') !! write(*,'(a)') join(s,left='[',right=']') !! write(*,'(a)') join(s,left='>>') !! end program demo_join !! !! Expected output: !! !! United we stand, divided we fall. !! United we stand, divided we fall. !! United | we | stand, | divided | we fall. !! United | we | stand, | divided | we fall. !! United | we | stand, | divided | we fall. !! United<> we<> stand,<> divided<> we fall. !! [United];[ we];[ stand,];[ divided];[ we fall.] !! [United][ we][ stand,][ divided][ we fall.] !! >>United>> we>> stand,>> divided>> we fall. pure function join ( str , sep , trm , left , right , start , end ) result ( string ) ! @(#)M_strings::join(3f): merge string array into a single CHARACTER value adding specified separators, caps, prefix and suffix character ( len =* ), intent ( in ) :: str (:) character ( len =* ), intent ( in ), optional :: sep , right , left , start , end logical , intent ( in ), optional :: trm character ( len = :), allocatable :: sep_local , left_local , right_local character ( len = :), allocatable :: string logical :: trm_local integer :: i if ( present ( sep )) then ; sep_local = sep ; else ; sep_local = '' ; endif if ( present ( trm )) then ; trm_local = trm ; else ; trm_local = . true . ; endif if ( present ( left )) then ; left_local = left ; else ; left_local = '' ; endif if ( present ( right )) then ; right_local = right ; else ; right_local = '' ; endif string = '' if ( size ( str ) == 0 ) then string = string // left_local // right_local else do i = 1 , size ( str ) - 1 if ( trm_local ) then string = string // left_local // trim ( str ( i )) // right_local // sep_local else string = string // left_local // str ( i ) // right_local // sep_local endif enddo if ( trm_local ) then string = string // left_local // trim ( str ( i )) // right_local else string = string // left_local // str ( i ) // right_local endif endif if ( present ( start )) string = start // string if ( present ( end )) string = string // end end function join !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!## NAME !! glob(3f) - [fpm_strings:COMPARE] compare given string for match to !! pattern which may contain wildcard characters !! (LICENSE:PD) !! !!## SYNOPSIS !! !! logical function glob(string, pattern ) !! !! character(len=*),intent(in) :: string !! character(len=*),intent(in) :: pattern !! !!## DESCRIPTION !! glob(3f) compares given STRING for match to PATTERN which may !! contain wildcard characters. !! !! In this version to get a match the entire string must be described !! by PATTERN. Trailing whitespace is significant, so trim the input !! string to have trailing whitespace ignored. !! !!## OPTIONS !! string the input string to test to see if it contains the pattern. !! pattern the following simple globbing options are available !! !! o \"?\" matching any one character !! o \"*\" matching zero or more characters. !! Do NOT use adjacent asterisks. !! o Both strings may have trailing spaces which !! are ignored. !! o There is no escape character, so matching strings with !! literal question mark and asterisk is problematic. !! !!## EXAMPLES !! !! Example program !! !! program demo_glob !! implicit none !! ! This main() routine passes a bunch of test strings !! ! into the above code. In performance comparison mode, !! ! it does that over and over. Otherwise, it does it just !! ! once. Either way, it outputs a passed/failed result. !! ! !! integer :: nReps !! logical :: allpassed !! integer :: i !! allpassed = .true. !! !! nReps = 10000 !! ! Can choose as many repetitions as you're expecting !! ! in the real world. !! nReps = 1 !! !! do i=1,nReps !! ! Cases with repeating character sequences. !! allpassed=allpassed .and. test(\"a*abab\", \"a*b\", .true.) !! !!cycle !! allpassed=allpassed .and. test(\"ab\", \"*?\", .true.) !! allpassed=allpassed .and. test(\"abc\", \"*?\", .true.) !! allpassed=allpassed .and. test(\"abcccd\", \"*ccd\", .true.) !! allpassed=allpassed .and. test(\"bLah\", \"bLaH\", .false.) !! allpassed=allpassed .and. test(\"mississippi\", \"*sip*\", .true.) !! allpassed=allpassed .and. & !! & test(\"xxxx*zzzzzzzzy*f\", \"xxx*zzy*f\", .true.) !! allpassed=allpassed .and. & !! & test(\"xxxx*zzzzzzzzy*f\", \"xxxx*zzy*fffff\", .false.) !! allpassed=allpassed .and. & !! & test(\"mississipissippi\", \"*issip*ss*\", .true.) !! allpassed=allpassed .and. & !! & test(\"xxxxzzzzzzzzyf\", \"xxxx*zzy*fffff\", .false.) !! allpassed=allpassed .and. & !! & test(\"xxxxzzzzzzzzyf\", \"xxxx*zzy*f\", .true.) !! allpassed=allpassed .and. test(\"xyxyxyzyxyz\", \"xy*z*xyz\", .true.) !! allpassed=allpassed .and. test(\"xyxyxyxyz\", \"xy*xyz\", .true.) !! allpassed=allpassed .and. test(\"mississippi\", \"mi*sip*\", .true.) !! allpassed=allpassed .and. test(\"ababac\", \"*abac*\", .true.) !! allpassed=allpassed .and. test(\"aaazz\", \"a*zz*\", .true.) !! allpassed=allpassed .and. test(\"a12b12\", \"*12*23\", .false.) !! allpassed=allpassed .and. test(\"a12b12\", \"a12b\", .false.) !! allpassed=allpassed .and. test(\"a12b12\", \"*12*12*\", .true.) !! !! ! Additional cases where the '*' char appears in the tame string. !! allpassed=allpassed .and. test(\"*\", \"*\", .true.) !! allpassed=allpassed .and. test(\"a*r\", \"a*\", .true.) !! allpassed=allpassed .and. test(\"a*ar\", \"a*aar\", .false.) !! !! ! More double wildcard scenarios. !! allpassed=allpassed .and. test(\"XYXYXYZYXYz\", \"XY*Z*XYz\", .true.) !! allpassed=allpassed .and. test(\"missisSIPpi\", \"*SIP*\", .true.) !! allpassed=allpassed .and. test(\"mississipPI\", \"*issip*PI\", .true.) !! allpassed=allpassed .and. test(\"xyxyxyxyz\", \"xy*xyz\", .true.) !! allpassed=allpassed .and. test(\"miSsissippi\", \"mi*sip*\", .true.) !! allpassed=allpassed .and. test(\"miSsissippi\", \"mi*Sip*\", .false.) !! allpassed=allpassed .and. test(\"abAbac\", \"*Abac*\", .true.) !! allpassed=allpassed .and. test(\"aAazz\", \"a*zz*\", .true.) !! allpassed=allpassed .and. test(\"A12b12\", \"*12*23\", .false.) !! allpassed=allpassed .and. test(\"a12B12\", \"*12*12*\", .true.) !! allpassed=allpassed .and. test(\"oWn\", \"*oWn*\", .true.) !! !! ! Completely tame (no wildcards) cases. !! allpassed=allpassed .and. test(\"bLah\", \"bLah\", .true.) !! !! ! Simple mixed wildcard tests suggested by IBMer Marlin Deckert. !! allpassed=allpassed .and. test(\"a\", \"*?\", .true.) !! !! ! More mixed wildcard tests including coverage for false positives. !! allpassed=allpassed .and. test(\"a\", \"??\", .false.) !! allpassed=allpassed .and. test(\"ab\", \"?*?\", .true.) !! allpassed=allpassed .and. test(\"ab\", \"*?*?*\", .true.) !! allpassed=allpassed .and. test(\"abc\", \"?**?*?\", .true.) !! allpassed=allpassed .and. test(\"abc\", \"?**?*&?\", .false.) !! allpassed=allpassed .and. test(\"abcd\", \"?b*??\", .true.) !! allpassed=allpassed .and. test(\"abcd\", \"?a*??\", .false.) !! allpassed=allpassed .and. test(\"abcd\", \"?**?c?\", .true.) !! allpassed=allpassed .and. test(\"abcd\", \"?**?d?\", .false.) !! allpassed=allpassed .and. test(\"abcde\", \"?*b*?*d*?\", .true.) !! !! ! Single-character-match cases. !! allpassed=allpassed .and. test(\"bLah\", \"bL?h\", .true.) !! allpassed=allpassed .and. test(\"bLaaa\", \"bLa?\", .false.) !! allpassed=allpassed .and. test(\"bLah\", \"bLa?\", .true.) !! allpassed=allpassed .and. test(\"bLaH\", \"?Lah\", .false.) !! allpassed=allpassed .and. test(\"bLaH\", \"?LaH\", .true.) !! !! ! Many-wildcard scenarios. !! allpassed=allpassed .and. test(& !! &\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa& !! &aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab\",& !! &\"a*a*a*a*a*a*aa*aaa*a*a*b\",& !! &.true.) !! allpassed=allpassed .and. test(& !! &\"abababababababababababababababababababaacacacacacacac& !! &adaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\",& !! &\"*a*b*ba*ca*a*aa*aaa*fa*ga*b*\",& !! &.true.) !! allpassed=allpassed .and. test(& !! &\"abababababababababababababababababababaacacacacacaca& !! &cadaeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\",& !! &\"*a*b*ba*ca*a*x*aaa*fa*ga*b*\",& !! &.false.) !! allpassed=allpassed .and. test(& !! &\"abababababababababababababababababababaacacacacacacacad& !! &aeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\",& !! &\"*a*b*ba*ca*aaaa*fa*ga*gggg*b*\",& !! &.false.) !! allpassed=allpassed .and. test(& !! &\"abababababababababababababababababababaacacacacacacacad& !! &aeafagahaiajakalaaaaaaaaaaaaaaaaaffafagaagggagaaaaaaaab\",& !! &\"*a*b*ba*ca*aaaa*fa*ga*ggg*b*\",& !! &.true.) !! allpassed=allpassed .and. test(\"aaabbaabbaab\", \"*aabbaa*a*\", .true.) !! allpassed=allpassed .and. & !! test(\"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\",& !! &\"a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\", .true.) !! allpassed=allpassed .and. test(\"aaaaaaaaaaaaaaaaa\",& !! &\"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\", .true.) !! allpassed=allpassed .and. test(\"aaaaaaaaaaaaaaaa\",& !! &\"*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*\", .false.) !! allpassed=allpassed .and. test(& !! &\"abc*abcd*abcde*abcdef*abcdefg*abcdefgh*abcdefghi*abcdefghij& !! &*abcdefghijk*abcdefghijkl*abcdefghijklm*abcdefghijklmn\",& !! & \"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc& !! &*abc*abc*abc*\",& !! &.false.) !! allpassed=allpassed .and. test(& !! &\"abc*abcd*abcde*abcdef*abcdefg*abcdefgh*abcdefghi*abcdefghij& !! &*abcdefghijk*abcdefghijkl*abcdefghijklm*abcdefghijklmn\",& !! &\"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*\",& !! &.true.) !! allpassed=allpassed .and. test(\"abc*abcd*abcd*abc*abcd\",& !! &\"abc*abc*abc*abc*abc\", .false.) !! allpassed=allpassed .and. test( \"abc*abcd*abcd*abc*abcd*abcd& !! &*abc*abcd*abc*abc*abcd\", & !! &\"abc*abc*abc*abc*abc*abc*abc*abc*abc*abc*abcd\",& !! &.true.) !! allpassed=allpassed .and. test(\"abc\",& !! &\"********a********b********c********\", .true.) !! allpassed=allpassed .and.& !! &test(\"********a********b********c********\", \"abc\", .false.) !! allpassed=allpassed .and. & !! &test(\"abc\", \"********a********b********b********\", .false.) !! allpassed=allpassed .and. test(\"*abc*\", \"***a*b*c***\", .true.) !! !! ! A case-insensitive algorithm test. !! ! allpassed=allpassed .and. test(\"mississippi\", \"*issip*PI\", .true.) !! enddo !! !! if (allpassed)then !! write(*,'(a)')\"Passed\",nReps !! else !! write(*,'(a)')\"Failed\" !! endif !! contains !! ! This is a test program for wildcard matching routines. !! ! It can be used either to test a single routine for correctness, !! ! or to compare the timings of two (or more) different wildcard !! ! matching routines. !! ! !! function test(tame, wild, bExpectedResult) result(bpassed) !! use fpm_strings, only : glob !! character(len=*) :: tame !! character(len=*) :: wild !! logical :: bExpectedResult !! logical :: bResult !! logical :: bPassed !! bResult = .true. ! We'll do \"&=\" cumulative checking. !! bPassed = .false. ! Assume the worst. !! write(*,*)repeat('=',79) !! bResult = glob(tame, wild) ! Call a wildcard matching routine. !! !! ! To assist correctness checking, output the two strings in any !! ! failing scenarios. !! if (bExpectedResult .eqv. bResult) then !! bPassed = .true. !! if(nReps == 1) write(*,*)\"Passed match on \",tame,\" vs. \", wild !! else !! if(nReps == 1) write(*,*)\"Failed match on \",tame,\" vs. \", wild !! endif !! !! end function test !! end program demo_glob !! !! Expected output !! !! !!## REFERENCE !! The article \"Matching Wildcards: An Empirical Way to Tame an Algorithm\" !! in Dr Dobb's Journal, By Kirk J. Krauss, October 07, 2014 !! function glob ( tame , wild ) ! @(#)fpm_strings::glob(3f): function compares text strings, one of which can have wildcards ('*' or '?'). logical :: glob !! result of test character ( len =* ) :: tame !! A string without wildcards to compare to the globbing expression character ( len =* ) :: wild !! A (potentially) corresponding string with wildcards character ( len = len ( tame ) + 1 ) :: tametext character ( len = len ( wild ) + 1 ) :: wildtext character ( len = 1 ), parameter :: NULL = char ( 0 ) integer :: wlen integer :: ti , wi integer :: i character ( len = :), allocatable :: tbookmark , wbookmark ! These two values are set when we observe a wildcard character. They ! represent the locations, in the two strings, from which we start once we've observed it. tametext = tame // NULL wildtext = wild // NULL tbookmark = NULL wbookmark = NULL wlen = len ( wild ) wi = 1 ti = 1 do ! Walk the text strings one character at a time. if ( wildtext ( wi : wi ) == '*' ) then ! How do you match a unique text string? do i = wi , wlen ! Easy: unique up on it! if ( wildtext ( wi : wi ) == '*' ) then wi = wi + 1 else exit endif enddo if ( wildtext ( wi : wi ) == NULL ) then ! \"x\" matches \"*\" glob = . true . return endif if ( wildtext ( wi : wi ) /= '?' ) then ! Fast-forward to next possible match. do while ( tametext ( ti : ti ) /= wildtext ( wi : wi )) ti = ti + 1 if ( tametext ( ti : ti ) == NULL ) then glob = . false . return ! \"x\" doesn't match \"*y*\" endif enddo endif wbookmark = wildtext ( wi :) tbookmark = tametext ( ti :) elseif ( tametext ( ti : ti ) /= wildtext ( wi : wi ) . and . wildtext ( wi : wi ) /= '?' ) then ! Got a non-match. If we've set our bookmarks, back up to one or both of them and retry. if ( wbookmark /= NULL ) then if ( wildtext ( wi :) /= wbookmark ) then wildtext = wbookmark ; wlen = len_trim ( wbookmark ) wi = 1 ! Don't go this far back again. if ( tametext ( ti : ti ) /= wildtext ( wi : wi )) then tbookmark = tbookmark ( 2 :) tametext = tbookmark ti = 1 cycle ! \"xy\" matches \"*y\" else wi = wi + 1 endif endif if ( tametext ( ti : ti ) /= NULL ) then ti = ti + 1 cycle ! \"mississippi\" matches \"*sip*\" endif endif glob = . false . return ! \"xy\" doesn't match \"x\" endif ti = ti + 1 wi = wi + 1 if ( tametext ( ti : ti ) == NULL ) then ! How do you match a tame text string? if ( wildtext ( wi : wi ) /= NULL ) then do while ( wildtext ( wi : wi ) == '*' ) ! The tame way: unique up on it! wi = wi + 1 ! \"x\" matches \"x*\" if ( wildtext ( wi : wi ) == NULL ) exit enddo endif if ( wildtext ( wi : wi ) == NULL ) then glob = . true . return ! \"x\" matches \"x\" endif glob = . false . return ! \"x\" doesn't match \"xy\" endif enddo end function glob !> Returns the length of the string representation of 'i' pure integer function str_int_len ( i ) result ( sz ) integer , intent ( in ) :: i integer , parameter :: MAX_STR = 100 character ( MAX_STR ) :: s ! If 's' is too short (MAX_STR too small), Fortran will abort with: ! \"Fortran runtime error: End of record\" write ( s , '(i0)' ) i sz = len_trim ( s ) end function !> Converts integer \"i\" to string pure function str_int ( i ) result ( s ) integer , intent ( in ) :: i character ( len = str_int_len ( i )) :: s write ( s , '(i0)' ) i end function !> Returns the length of the string representation of 'i' pure integer function str_int64_len ( i ) result ( sz ) integer ( int64 ), intent ( in ) :: i integer , parameter :: MAX_STR = 100 character ( MAX_STR ) :: s ! If 's' is too short (MAX_STR too small), Fortran will abort with: ! \"Fortran runtime error: End of record\" write ( s , '(i0)' ) i sz = len_trim ( s ) end function !> Converts integer \"i\" to string pure function str_int64 ( i ) result ( s ) integer ( int64 ), intent ( in ) :: i character ( len = str_int64_len ( i )) :: s write ( s , '(i0)' ) i end function !> Returns the length of the string representation of 'l' pure integer function str_logical_len ( l ) result ( sz ) logical , intent ( in ) :: l if ( l ) then sz = 6 else sz = 7 end if end function !> Converts logical \"l\" to string pure function str_logical ( l ) result ( s ) logical , intent ( in ) :: l character ( len = str_logical_len ( l )) :: s if ( l ) then s = \".true.\" else s = \".false.\" end if end function !> Returns string with special characters replaced with an underscore. !! For now, only a hyphen is treated as a special character, but this can be !! expanded to other characters if needed. pure function to_fortran_name ( string ) result ( res ) character ( * ), intent ( in ) :: string character ( len ( string )) :: res character , parameter :: SPECIAL_CHARACTERS ( * ) = [ '-' ] res = replace ( string , SPECIAL_CHARACTERS , '_' ) end function to_fortran_name elemental function is_fortran_name ( line ) result ( lout ) ! determine if a string is a valid Fortran name ignoring trailing spaces ! (but not leading spaces) character ( len =* ), parameter :: int = '0123456789' character ( len =* ), parameter :: lower = 'abcdefghijklmnopqrstuvwxyz' character ( len =* ), parameter :: upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' character ( len =* ), parameter :: allowed = upper // lower // int // '_' character ( len =* ), intent ( in ) :: line character ( len = :), allocatable :: name logical :: lout name = trim ( line ) if ( len ( name ) /= 0 ) then lout = . true . & & . and . verify ( name ( 1 : 1 ), lower // upper ) == 0 & & . and . verify ( name , allowed ) == 0 & & . and . len ( name ) <= 63 else lout = . false . endif end function is_fortran_name !> Check that a module name fits the current naming rules: !> 1) It must be a valid FORTRAN name (<=63 chars, begin with letter, \"_\" is only allowed non-alphanumeric) !> 2) It must begin with the package name !> 3) If longer, package name must be followed by default separator plus at least one char logical function is_valid_module_name ( module_name , package_name , custom_prefix , enforce_module_names ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: package_name type ( string_t ), intent ( in ) :: custom_prefix logical , intent ( in ) :: enforce_module_names !> Basic check: check the name is Fortran-compliant valid = is_fortran_name ( module_name % s ); if (. not . valid ) return !> FPM package enforcing: check that the module name begins with the package name if ( enforce_module_names ) then ! Default prefixing is always valid valid = has_valid_standard_prefix ( module_name , package_name ) ! If a custom prefix was validated, it provides additional naming options ! Because they never overlap with the default prefix, the former is always an option if ( len_trim ( custom_prefix ) > 0 . and . . not . valid ) & valid = has_valid_custom_prefix ( module_name , custom_prefix ) end if end function is_valid_module_name !> Check that a custom module prefix fits the current naming rules: !> 1) Only alphanumeric characters (no spaces, dashes, underscores or other characters) !> 2) Does not begin with a number (Fortran-compatible syntax) logical function is_valid_module_prefix ( module_prefix ) result ( valid ) type ( string_t ), intent ( in ) :: module_prefix character ( len =* ), parameter :: num = '0123456789' character ( len =* ), parameter :: lower = 'abcdefghijklmnopqrstuvwxyz' character ( len =* ), parameter :: upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' character ( len =* ), parameter :: alpha = upper // lower character ( len =* ), parameter :: allowed = alpha // num character ( len = :), allocatable :: name name = trim ( module_prefix % s ) if ( len ( name ) > 0 . and . len ( name ) <= 63 ) then valid = verify ( name ( 1 : 1 ), alpha ) == 0 . and . & verify ( name , allowed ) == 0 else valid = . false . endif end function is_valid_module_prefix type ( string_t ) function module_prefix_template ( project_name , custom_prefix ) result ( prefix ) type ( string_t ), intent ( in ) :: project_name type ( string_t ), intent ( in ) :: custom_prefix if ( is_valid_module_prefix ( custom_prefix )) then prefix = string_t ( trim ( custom_prefix % s ) // \"_\" ) else prefix = string_t ( to_fortran_name ( project_name % s ) // \"__\" ) end if end function module_prefix_template type ( string_t ) function module_prefix_type ( project_name , custom_prefix ) result ( ptype ) type ( string_t ), intent ( in ) :: project_name type ( string_t ), intent ( in ) :: custom_prefix if ( is_valid_module_prefix ( custom_prefix )) then ptype = string_t ( \"custom\" ) else ptype = string_t ( \"default\" ) end if end function module_prefix_type !> Check that a module name is prefixed with a custom prefix: !> 1) It must be a valid FORTRAN name subset (<=63 chars, begin with letter, only alphanumeric allowed) !> 2) It must begin with the prefix !> 3) If longer, package name must be followed by default separator (\"_\") plus at least one char logical function has_valid_custom_prefix ( module_name , custom_prefix ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: custom_prefix !> custom_module separator: single underscore character ( * ), parameter :: SEP = \"_\" logical :: is_same , has_separator , same_beginning integer :: lpkg , lmod , lsep !> Basic check: check that both names are individually valid valid = is_fortran_name ( module_name % s ) . and . & is_valid_module_prefix ( custom_prefix ) !> FPM package enforcing: check that the module name begins with the custom prefix if ( valid ) then !> Query string lengths lpkg = len_trim ( custom_prefix ) lmod = len_trim ( module_name ) lsep = len_trim ( SEP ) same_beginning = str_begins_with_str ( module_name % s , custom_prefix % s , case_sensitive = . false .) is_same = lpkg == lmod . and . same_beginning if ( lmod >= lpkg + lsep ) then has_separator = str_begins_with_str ( module_name % s ( lpkg + 1 : lpkg + lsep ), SEP ) else has_separator = . false . endif !> 2) It must begin with the package name. !> 3) It can be equal to the package name, or, if longer, must be followed by the ! default separator plus at least one character !> 4) Package name must not end with an underscore valid = same_beginning . and . ( is_same . or . ( lmod > lpkg + lsep . and . has_separator )) end if end function has_valid_custom_prefix !> Check that a module name is prefixed with the default package prefix: !> 1) It must be a valid FORTRAN name (<=63 chars, begin with letter, \"_\" is only allowed non-alphanumeric) !> 2) It must begin with the package name !> 3) If longer, package name must be followed by default separator plus at least one char logical function has_valid_standard_prefix ( module_name , package_name ) result ( valid ) type ( string_t ), intent ( in ) :: module_name type ( string_t ), intent ( in ) :: package_name !> Default package__module separator: two underscores character ( * ), parameter :: SEP = \"__\" character ( len = :), allocatable :: fortranized_pkg logical :: is_same , has_separator , same_beginning integer :: lpkg , lmod , lsep !> Basic check: check the name is Fortran-compliant valid = is_fortran_name ( module_name % s ) !> FPM package enforcing: check that the module name begins with the package name if ( valid ) then fortranized_pkg = to_fortran_name ( package_name % s ) !> Query string lengths lpkg = len_trim ( fortranized_pkg ) lmod = len_trim ( module_name ) lsep = len_trim ( SEP ) same_beginning = str_begins_with_str ( module_name % s , fortranized_pkg , case_sensitive = . false .) is_same = lpkg == lmod . and . same_beginning if ( lmod >= lpkg + lsep ) then has_separator = str_begins_with_str ( module_name % s ( lpkg + 1 : lpkg + lsep ), SEP ) else has_separator = . false . endif !> 2) It must begin with the package name. !> 3) It can be equal to the package name, or, if longer, must be followed by the ! default separator plus at least one character !> 4) Package name must not end with an underscore valid = is_fortran_name ( fortranized_pkg ) . and . & fortranized_pkg ( lpkg : lpkg ) /= '_' . and . & ( same_beginning . and . ( is_same . or . ( lmod > lpkg + lsep . and . has_separator ))) end if end function has_valid_standard_prefix !> Check that two string _objects_ are exactly identical pure logical function string_is_same ( this , that ) !> two strings to be compared type ( string_t ), intent ( in ) :: this , that integer :: i string_is_same = . false . if ( allocated ( this % s ). neqv . allocated ( that % s )) return if ( allocated ( this % s )) then if (. not . len ( this % s ) == len ( that % s )) return if (. not . len_trim ( this % s ) == len_trim ( that % s )) return do i = 1 , len_trim ( this % s ) if (. not .( this % s ( i : i ) == that % s ( i : i ))) return end do end if ! All checks passed string_is_same = . true . end function string_is_same !> Check that two allocatable string _object_ arrays are exactly identical pure logical function string_arrays_same ( this , that ) !> two string arrays to be compared type ( string_t ), allocatable , intent ( in ) :: this (:), that (:) integer :: i string_arrays_same = . false . if ( allocated ( this ). neqv . allocated ( that )) return if ( allocated ( this )) then if (. not .( size ( this ) == size ( that ))) return if (. not .( ubound ( this , 1 ) == ubound ( that , 1 ))) return if (. not .( lbound ( this , 1 ) == lbound ( that , 1 ))) return do i = lbound ( this , 1 ), ubound ( this , 1 ) if (. not . string_is_same ( this ( i ), that ( i ))) return end do end if ! All checks passed string_arrays_same = . true . end function string_arrays_same ! Remove all characters from a set from a string subroutine remove_characters_in_set ( string , set , replace_with ) character ( len = :), allocatable , intent ( inout ) :: string character ( * ), intent ( in ) :: set character , optional , intent ( in ) :: replace_with ! Replace with this character instead of removing integer :: feed , length if (. not . allocated ( string )) return if ( len ( set ) <= 0 ) return length = len ( string ) feed = scan ( string , set ) do while ( length > 0 . and . feed > 0 ) ! Remove heading if ( length == 1 ) then string = \"\" elseif ( feed == 1 ) then string = string ( 2 : length ) ! Remove trailing elseif ( feed == length ) then string = string ( 1 : length - 1 ) ! In between: replace with given character elseif ( present ( replace_with )) then string ( feed : feed ) = replace_with ! Or just remove else string = string ( 1 : feed - 1 ) // string ( feed + 1 : length ) end if length = len ( string ) feed = scan ( string , set ) end do end subroutine remove_characters_in_set ! Remove all new line characters from the current string, replace them with spaces subroutine remove_newline_characters ( string ) type ( string_t ), intent ( inout ) :: string integer :: feed , length character ( * ), parameter :: CRLF = achar ( 13 ) // new_line ( 'a' ) character ( * ), parameter :: SPACE = ' ' call remove_characters_in_set ( string % s , set = CRLF , replace_with = SPACE ) end subroutine remove_newline_characters !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!### NAME !! notabs(3f) - [fpm_strings:NONALPHA] expand tab characters !! (LICENSE:PD) !! !!### SYNOPSIS !! !! subroutine notabs(INSTR,OUTSTR,ILEN) !! !! character(len=*),intent=(in) :: INSTR !! character(len=*),intent=(out) :: OUTSTR !! integer,intent=(out) :: ILEN !! !!### DESCRIPTION !! NOTABS() converts tabs in INSTR to spaces in OUTSTR while maintaining !! columns. It assumes a tab is set every 8 characters. Trailing spaces !! are removed. !! !! In addition, trailing carriage returns and line feeds are removed !! (they are usually a problem created by going to and from MSWindows). !! !! What are some reasons for removing tab characters from an input line? !! Some Fortran compilers have problems with tabs, as tabs are not !! part of the Fortran character set. Some editors and printers will !! have problems with tabs. It is often useful to expand tabs in input !! files to simplify further processing such as tokenizing an input line. !! !!### OPTIONS !! instr Input line to remove tabs from !! !!### RESULTS !! outstr Output string with tabs expanded. Assumed to be of sufficient !! length !! ilen Significant length of returned string !! !!### EXAMPLES !! !! Sample program: !! !! program demo_notabs !! !! ! test filter to remove tabs and trailing white space from input !! ! on files up to 1024 characters wide !! use fpm_strings, only : notabs !! character(len=1024) :: in,out !! integer :: ios,iout !! do !! read(*,'(A)',iostat=ios)in !! if(ios /= 0) exit !! call notabs(in,out,iout) !! write(*,'(a)')out(:iout) !! enddo !! end program demo_notabs !! !!### SEE ALSO !! GNU/Unix commands expand(1) and unexpand(1) !! elemental impure subroutine notabs ( instr , outstr , ilen ) ! ident_31=\"@(#)fpm_strings::notabs(3f): convert tabs to spaces while maintaining columns, remove CRLF chars\" character ( len =* ), intent ( in ) :: instr ! input line to scan for tab characters character ( len =* ), intent ( out ) :: outstr ! tab-expanded version of INSTR produced integer , intent ( out ) :: ilen ! column position of last character put into output string ! that is, ILEN holds the position of the last non-blank character in OUTSTR integer , parameter :: tabsize = 8 ! assume a tab stop is set every 8th column integer :: ipos ! position in OUTSTR to put next character of INSTR integer :: lenin ! length of input string trimmed of trailing spaces integer :: lenout ! number of characters output string can hold integer :: istep ! counter that advances thru input string INSTR one character at a time character ( len = 1 ) :: c ! character in input line being processed integer :: iade ! ADE (ASCII Decimal Equivalent) of character being tested ipos = 1 ! where to put next character in output string OUTSTR lenin = len_trim ( instr ( 1 : len ( instr ) )) ! length of INSTR trimmed of trailing spaces lenout = len ( outstr ) ! number of characters output string OUTSTR can hold outstr = \" \" ! this SHOULD blank-fill string, a buggy machine required a loop to set all characters SCAN_LINE : do istep = 1 , lenin ! look through input string one character at a time c = instr ( istep : istep ) ! get next character iade = ichar ( c ) ! get ADE of the character EXPAND_TABS : select case ( iade ) ! take different actions depending on which character was found case ( 9 ) ! test if character is a tab and move pointer out to appropriate column ipos = ipos + ( tabsize - ( mod ( ipos - 1 , tabsize ))) case ( 10 , 13 ) ! convert carriage-return and new-line to space ,typically to handle DOS-format files ipos = ipos + 1 case default ! c is anything else other than a tab,newline,or return insert it in output string if ( ipos > lenout ) then write ( stderr , * ) \"*notabs* output string overflow\" exit else outstr ( ipos : ipos ) = c ipos = ipos + 1 endif end select EXPAND_TABS enddo SCAN_LINE ipos = min ( ipos , lenout ) ! tabs or newline or return characters or last character might have gone too far ilen = len_trim ( outstr (: ipos )) ! trim trailing spaces end subroutine notabs !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!##NAME !! dilate(3f) - [M_strings:NONALPHA] expand tab characters !! (LICENSE:PD) !! !!##SYNOPSIS !! !! function dilate(INSTR) result(OUTSTR) !! !! character(len=*),intent=(in) :: INSTR !! character(len=:),allocatable :: OUTSTR !! !!##DESCRIPTION !! dilate() converts tabs in INSTR to spaces in OUTSTR. It assumes a !! tab is set every 8 characters. Trailing spaces are removed. !! !! In addition, trailing carriage returns and line feeds are removed !! (they are usually a problem created by going to and from MSWindows). !! !!##OPTIONS !! instr Input line to remove tabs from !! !!##RESULTS !! outstr Output string with tabs expanded. !! !!##EXAMPLES !! !! Sample program: !! !! program demo_dilate !! !! use M_strings, only : dilate !! implicit none !! character(len=:),allocatable :: in !! integer :: i !! in=' this is my string ' !! ! change spaces to tabs to make a sample input !! do i=1,len(in) !! if(in(i:i) == ' ')in(i:i)=char(9) !! enddo !! write(*,'(a)')in,dilate(in) !! end program demo_dilate !! function dilate ( instr ) result ( outstr ) character ( len =* ), intent ( in ) :: instr ! input line to scan for tab characters character ( len = :), allocatable :: outstr ! tab-expanded version of INSTR produced integer :: i integer :: icount integer :: lgth icount = 0 do i = 1 , len ( instr ) if ( instr ( i : i ) == char ( 9 )) icount = icount + 1 end do allocate ( character ( len = ( len ( instr ) + 8 * icount )) :: outstr ) call notabs ( instr , outstr , lgth ) outstr = outstr (: lgth ) end function dilate end module fpm_strings","tags":"","loc":"sourcefile/fpm_strings.f90.html"},{"title":"fpm_environment.f90 – Fortran-lang/fpm","text":"Source Code !> This module contains procedures that interact with the programming environment. !! !! * [get_os_type] -- Determine the OS type !! * [get_env] -- return the value of an environment variable module fpm_environment use , intrinsic :: iso_fortran_env , only : stdin => input_unit , & & stdout => output_unit , & & stderr => error_unit use , intrinsic :: iso_c_binding , only : c_char , c_int , c_null_char use fpm_error , only : fpm_stop implicit none private public :: get_os_type public :: os_is_unix public :: get_env public :: set_env public :: delete_env public :: get_command_arguments_quoted public :: separator public :: OS_NAME integer , parameter , public :: OS_UNKNOWN = 0 integer , parameter , public :: OS_LINUX = 1 integer , parameter , public :: OS_MACOS = 2 integer , parameter , public :: OS_WINDOWS = 3 integer , parameter , public :: OS_CYGWIN = 4 integer , parameter , public :: OS_SOLARIS = 5 integer , parameter , public :: OS_FREEBSD = 6 integer , parameter , public :: OS_OPENBSD = 7 contains !> Return string describing the OS type flag pure function OS_NAME ( os ) integer , intent ( in ) :: os character ( len = :), allocatable :: OS_NAME select case ( os ) case ( OS_LINUX ); OS_NAME = \"Linux\" case ( OS_MACOS ); OS_NAME = \"macOS\" case ( OS_WINDOWS ); OS_NAME = \"Windows\" case ( OS_CYGWIN ); OS_NAME = \"Cygwin\" case ( OS_SOLARIS ); OS_NAME = \"Solaris\" case ( OS_FREEBSD ); OS_NAME = \"FreeBSD\" case ( OS_OPENBSD ); OS_NAME = \"OpenBSD\" case ( OS_UNKNOWN ); OS_NAME = \"Unknown\" case default ; OS_NAME = \"UNKNOWN\" end select end function OS_NAME !> Determine the OS type integer function get_os_type () result ( r ) !! !! Returns one of OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, OS_CYGWIN, !! OS_SOLARIS, OS_FREEBSD, OS_OPENBSD. !! !! At first, the environment variable `OS` is checked, which is usually !! found on Windows. Then, `OSTYPE` is read in and compared with common !! names. If this fails too, check the existence of files that can be !! found on specific system types only. !! !! Returns OS_UNKNOWN if the operating system cannot be determined. character ( len = 255 ) :: val integer :: length , rc logical :: file_exists logical , save :: first_run = . true . integer , save :: ret = OS_UNKNOWN !$omp threadprivate(ret, first_run) if (. not . first_run ) then r = ret return end if first_run = . false . r = OS_UNKNOWN ! Check environment variable `OSTYPE`. call get_environment_variable ( 'OSTYPE' , val , length , rc ) if ( rc == 0 . and . length > 0 ) then ! Linux if ( index ( val , 'linux' ) > 0 ) then r = OS_LINUX ret = r return end if ! macOS if ( index ( val , 'darwin' ) > 0 ) then r = OS_MACOS ret = r return end if ! Windows, MSYS, MinGW, Git Bash if ( index ( val , 'win' ) > 0 . or . index ( val , 'msys' ) > 0 ) then r = OS_WINDOWS ret = r return end if ! Cygwin if ( index ( val , 'cygwin' ) > 0 ) then r = OS_CYGWIN ret = r return end if ! Solaris, OpenIndiana, ... if ( index ( val , 'SunOS' ) > 0 . or . index ( val , 'solaris' ) > 0 ) then r = OS_SOLARIS ret = r return end if ! FreeBSD if ( index ( val , 'FreeBSD' ) > 0 . or . index ( val , 'freebsd' ) > 0 ) then r = OS_FREEBSD ret = r return end if ! OpenBSD if ( index ( val , 'OpenBSD' ) > 0 . or . index ( val , 'openbsd' ) > 0 ) then r = OS_OPENBSD ret = r return end if end if ! Check environment variable `OS`. call get_environment_variable ( 'OS' , val , length , rc ) if ( rc == 0 . and . length > 0 . and . index ( val , 'Windows_NT' ) > 0 ) then r = OS_WINDOWS ret = r return end if ! Linux inquire ( file = '/etc/os-release' , exist = file_exists ) if ( file_exists ) then r = OS_LINUX ret = r return end if ! macOS inquire ( file = '/usr/bin/sw_vers' , exist = file_exists ) if ( file_exists ) then r = OS_MACOS ret = r return end if ! FreeBSD inquire ( file = '/bin/freebsd-version' , exist = file_exists ) if ( file_exists ) then r = OS_FREEBSD ret = r return end if end function get_os_type !> Compare the output of [[get_os_type]] or the optional !! passed INTEGER value to the value for OS_WINDOWS !! and return .TRUE. if they match and .FALSE. otherwise logical function os_is_unix ( os ) integer , intent ( in ), optional :: os integer :: build_os if ( present ( os )) then build_os = os else build_os = get_os_type () end if os_is_unix = build_os /= OS_WINDOWS end function os_is_unix !> get named environment variable value. It it is blank or !! not set return the optional default value function get_env ( NAME , DEFAULT ) result ( VALUE ) implicit none !> name of environment variable to get the value of character ( len =* ), intent ( in ) :: NAME !> default value to return if the requested value is undefined or blank character ( len =* ), intent ( in ), optional :: DEFAULT !> the returned value character ( len = :), allocatable :: VALUE integer :: howbig integer :: stat integer :: length ! get length required to hold value length = 0 if ( NAME /= '' ) then call get_environment_variable ( NAME , length = howbig , status = stat , trim_name = . true .) select case ( stat ) case ( 1 ) !*!print *, NAME, \" is not defined in the environment. Strange...\" VALUE = '' case ( 2 ) !*!print *, \"This processor doesn't support environment variables. Boooh!\" VALUE = '' case default ! make string to hold value of sufficient size allocate ( character ( len = max ( howbig , 1 )) :: VALUE ) ! get value call get_environment_variable ( NAME , VALUE , status = stat , trim_name = . true .) if ( stat /= 0 ) VALUE = '' end select else VALUE = '' endif if ( VALUE == '' . and . present ( DEFAULT )) VALUE = DEFAULT end function get_env function get_command_arguments_quoted () result ( args ) character ( len = :), allocatable :: args character ( len = :), allocatable :: arg character ( len = 1 ) :: quote integer :: ilength , istatus , i ilength = 0 args = '' quote = merge ( '\"' , \"'\" , separator () == '\\') do i=2,command_argument_count() ! look at all arguments after subcommand call get_command_argument(number=i,length=ilength,status=istatus) if(istatus /= 0) then write(stderr,' ( * ( g0 , 1 x )) ')' < ERROR >* get_command_arguments_stack * error obtaining argument ',i exit else if(allocated(arg))deallocate(arg) allocate(character(len=ilength) :: arg) call get_command_argument(number=i,value=arg,length=ilength,status=istatus) if(istatus /= 0) then write(stderr,' ( * ( g0 , 1 x )) ')' < ERROR >* get_command_arguments_stack * error obtaining argument ',i exit elseif(ilength>0)then if(index(arg//' ',' - ')/=1)then args=args//quote//arg//quote//' ' elseif(index(arg,' ')/=0)then args=args//quote//arg//quote//' ' else args=args//arg//' ' endif else args=args//repeat(quote,2)//' ' endif endif enddo end function get_command_arguments_quoted function separator() result(sep) !> !!##NAME !! separator(3f) - [M_io:ENVIRONMENT] try to determine pathname directory separator character !! (LICENSE:PD) !! !!##SYNOPSIS !! !! function separator() result(sep) !! !! character(len=1) :: sep !! !!##DESCRIPTION !! First using the name the program was invoked with, then the name !! returned by an INQUIRE(3f) of that name, then \".\\NAME\" and \"./NAME\" !! try to determine the separator character used to separate directory !! names from file basenames. !! !! If a slash or backslash is not found in the name, the environment !! variable PATH is examined first for a backslash, then a slash. !! !! Can be very system dependent. If the queries fail the default returned !! is \"/\". !! !!##EXAMPLE !! !! sample usage !! !! program demo_separator !! use M_io, only : separator !! implicit none !! write(*,*)' separator = ',separator() !! end program demo_separator ! use the pathname returned as arg0 to determine pathname separator implicit none character(len=:),allocatable :: arg0 integer :: arg0_length integer :: istat logical :: existing character(len=1) :: sep !*ifort_bug*!character(len=1),save :: sep_cache=' ' character(len=4096) :: name character(len=:),allocatable :: fname !*ifort_bug*! if(sep_cache/=' ')then ! use cached value. NOTE: A parallel code might theoretically use multiple OS !*ifort_bug*! sep=sep_cache !*ifort_bug*! return !*ifort_bug*! endif arg0_length=0 name=' ' call get_command_argument(0,length=arg0_length,status=istat) if(allocated(arg0))deallocate(arg0) allocate(character(len=arg0_length) :: arg0) call get_command_argument(0,arg0,status=istat) ! check argument name if(index(arg0,' \\ ')/=0)then sep=' \\ ' elseif(index(arg0,' / ')/=0)then sep=' / ' else ! try name returned by INQUIRE(3f) existing=.false. name=' ' inquire(file=arg0,iostat=istat,exist=existing,name=name) if(index(name,' \\ ')/=0)then sep=' \\ ' elseif(index(name,' / ')/=0)then sep=' / ' else ! well, try some common syntax and assume in current directory fname=' . \\ '//arg0 inquire(file=fname,iostat=istat,exist=existing) if(existing)then sep=' \\ ' else fname=' . / '//arg0 inquire(file=fname,iostat=istat,exist=existing) if(existing)then sep=' / ' else ! check environment variable PATH sep=merge(' \\ ',' / ',index(get_env(' PATH '),' \\ ')/=0) !*!write(*,*)' < WARNING > unknown system directory path separator ' endif endif endif endif !*ifort_bug*!sep_cache=sep end function separator !> Set an environment variable for the current environment using the C standard library logical function set_env ( name , value , overwrite ) !> Variable name character ( * ), intent ( in ) :: name !> Variable value character ( * ), intent ( in ) :: value !> Should a former value be overwritten? default = .true. logical , optional , intent ( in ) :: overwrite ! Local variables logical :: can_overwrite integer ( c_int ) :: cover , cerr character ( kind = c_char , len = 1 ), allocatable :: c_value (:), c_name (:) interface integer ( c_int ) function c_setenv ( envname , envval , overwrite ) & bind ( C , name = \"c_setenv\" ) import c_int , c_char implicit none !> Pointer to the name string character ( kind = c_char , len = 1 ), intent ( in ) :: envname ( * ) !> Pointer to the value string character ( kind = c_char , len = 1 ), intent ( in ) :: envval ( * ) !> Overwrite option integer ( c_int ), intent ( in ), value :: overwrite end function c_setenv end interface !> Overwrite setting can_overwrite = . true . if ( present ( overwrite )) can_overwrite = overwrite cover = merge ( 1_c_int , 0_c_int , can_overwrite ) !> C strings call f2cs ( name , c_name ) call f2cs ( value , c_value ) !> Call setenv #ifndef FPM_BOOTSTRAP cerr = c_setenv ( c_name , c_value , cover ) #endif set_env = cerr == 0_c_int end function set_env !> Deletes an environment variable for the current environment using the C standard library !> Returns an error if the variable did not exist in the first place logical function delete_env ( name ) result ( success ) !> Variable name character ( * ), intent ( in ) :: name ! Local variables integer ( c_int ) :: cerr character ( kind = c_char , len = 1 ), allocatable :: c_name (:) interface integer ( c_int ) function c_unsetenv ( envname ) bind ( C , name = \"c_unsetenv\" ) import c_int , c_char implicit none !> Pointer to the name string character ( kind = c_char , len = 1 ), intent ( in ) :: envname ( * ) end function c_unsetenv end interface !> C strings call f2cs ( name , c_name ) !> Call setenv #ifndef FPM_BOOTSTRAP cerr = c_unsetenv ( c_name ) #endif success = cerr == 0_c_int end function delete_env !> Fortran to C allocatable string pure subroutine f2cs ( f , c ) use iso_c_binding , only : c_char , c_null_char character ( * ), intent ( in ) :: f character ( len = 1 , kind = c_char ), allocatable , intent ( out ) :: c (:) integer :: lf , i lf = len ( f ) allocate ( c ( lf + 1 )) c ( lf + 1 ) = c_null_char forall ( i = 1 : lf ) c ( i ) = f ( i : i ) end subroutine f2cs end module fpm_environment","tags":"","loc":"sourcefile/fpm_environment.f90.html"},{"title":"fpm_backend.F90 – Fortran-lang/fpm","text":"Source Code !># Build backend !> Uses a list of `[[build_target_ptr]]` and a valid `[[fpm_model]]` instance !> to schedule and execute the compilation and linking of package targets. !> !> The package build process (`[[build_package]]`) comprises three steps: !> !> 1. __Target sorting:__ topological sort of the target dependency graph (`[[sort_target]]`) !> 2. __Target scheduling:__ group targets into schedule regions based on the sorting (`[[schedule_targets]]`) !> 3. __Target building:__ generate targets by compilation or linking !> !> @note If compiled with OpenMP, targets will be build in parallel where possible. !> !>### Incremental compilation !> The backend process supports *incremental* compilation whereby targets are not !> re-compiled if their corresponding dependencies have not been modified. !> !> - Source-based targets (*i.e.* objects) are not re-compiled if the corresponding source !> file is unmodified AND all of the target dependencies are not marked for re-compilation !> !> - Link targets (*i.e.* executables and libraries) are not re-compiled if the !> target output file already exists AND all of the target dependencies are not marked for !> re-compilation !> !> Source file modification is determined by a file digest (hash) which is calculated during !> the source parsing phase ([[fpm_source_parsing]]) and cached to disk after a target is !> successfully generated. !> module fpm_backend use , intrinsic :: iso_fortran_env , only : stdin => input_unit , stdout => output_unit , stderr => error_unit use fpm_error , only : fpm_stop use fpm_filesystem , only : basename , dirname , join_path , exists , mkdir , run , getline use fpm_model , only : fpm_model_t use fpm_strings , only : string_t , operator (. in .) use fpm_targets , only : build_target_t , build_target_ptr , FPM_TARGET_OBJECT , & FPM_TARGET_C_OBJECT , FPM_TARGET_ARCHIVE , FPM_TARGET_EXECUTABLE , & FPM_TARGET_CPP_OBJECT use fpm_backend_output implicit none private public :: build_package , sort_target , schedule_targets #ifndef FPM_BOOTSTRAP interface function c_isatty () bind ( C , name = 'c_isatty' ) use , intrinsic :: iso_c_binding , only : c_int integer ( c_int ) :: c_isatty end function end interface #endif contains !> Top-level routine to build package described by `model` subroutine build_package ( targets , model , verbose ) type ( build_target_ptr ), intent ( inout ) :: targets (:) type ( fpm_model_t ), intent ( in ) :: model logical , intent ( in ) :: verbose integer :: i , j type ( build_target_ptr ), allocatable :: queue (:) integer , allocatable :: schedule_ptr (:), stat (:) logical :: build_failed , skip_current type ( string_t ), allocatable :: build_dirs (:) type ( string_t ) :: temp type ( build_progress_t ) :: progress logical :: plain_output ! Need to make output directory for include (mod) files allocate ( build_dirs ( 0 )) do i = 1 , size ( targets ) associate ( target => targets ( i )% ptr ) if ( target % output_dir . in . build_dirs ) cycle temp % s = target % output_dir build_dirs = [ build_dirs , temp ] end associate end do do i = 1 , size ( build_dirs ) call mkdir ( build_dirs ( i )% s , verbose ) end do ! Perform depth-first topological sort of targets do i = 1 , size ( targets ) call sort_target ( targets ( i )% ptr ) end do ! Construct build schedule queue call schedule_targets ( queue , schedule_ptr , targets ) ! Check if queue is empty if (. not . verbose . and . size ( queue ) < 1 ) then write ( stderr , '(a)' ) 'Project is up to date' return end if ! Initialise build status flags allocate ( stat ( size ( queue ))) stat (:) = 0 build_failed = . false . ! Set output mode #ifndef FPM_BOOTSTRAP plain_output = (. not .( c_isatty () == 1 )) . or . verbose #else plain_output = . true . #endif progress = build_progress_t ( queue , plain_output ) ! Loop over parallel schedule regions do i = 1 , size ( schedule_ptr ) - 1 ! Build targets in schedule region i !$omp parallel do default(shared) private(skip_current) schedule(dynamic,1) do j = schedule_ptr ( i ),( schedule_ptr ( i + 1 ) - 1 ) ! Check if build already failed !$omp atomic read skip_current = build_failed if (. not . skip_current ) then call progress % compiling_status ( j ) call build_target ( model , queue ( j )% ptr , verbose , stat ( j )) call progress % completed_status ( j , stat ( j )) end if ! Set global flag if this target failed to build if ( stat ( j ) /= 0 ) then !$omp atomic write build_failed = . true . end if end do ! Check if this schedule region failed: exit with message if failed if ( build_failed ) then write ( * , * ) do j = 1 , size ( stat ) if ( stat ( j ) /= 0 ) Then call print_build_log ( queue ( j )% ptr ) end if end do do j = 1 , size ( stat ) if ( stat ( j ) /= 0 ) then write ( stderr , '(*(g0:,1x))' ) ' Compilation failed for object \"' , basename ( queue ( j )% ptr % output_file ), '\"' end if end do call fpm_stop ( 1 , 'stopping due to failed compilation' ) end if end do call progress % success () end subroutine build_package !> Topologically sort a target for scheduling by !> recursing over its dependencies. !> !> Checks disk-cached source hashes to determine if objects are !> up-to-date. Up-to-date sources are tagged as skipped. !> !> On completion, `target` should either be marked as !> sorted (`target%sorted=.true.`) or skipped (`target%skip=.true.`) !> !> If `target` is marked as sorted, `target%schedule` should be an !> integer greater than zero indicating the region for scheduling !> recursive subroutine sort_target ( target ) type ( build_target_t ), intent ( inout ), target :: target integer :: i , fh , stat ! Check if target has already been processed (as a dependency) if ( target % sorted . or . target % skip ) then return end if ! Check for a circular dependency ! (If target has been touched but not processed) if ( target % touched ) then call fpm_stop ( 1 , '(!) Circular dependency found with: ' // target % output_file ) else target % touched = . true . ! Set touched flag end if ! Load cached source file digest if present if (. not . allocated ( target % digest_cached ) . and . & exists ( target % output_file ) . and . & exists ( target % output_file // '.digest' )) then allocate ( target % digest_cached ) open ( newunit = fh , file = target % output_file // '.digest' , status = 'old' ) read ( fh , * , iostat = stat ) target % digest_cached close ( fh ) if ( stat /= 0 ) then ! Cached digest is not recognized deallocate ( target % digest_cached ) end if end if if ( allocated ( target % source )) then ! Skip if target is source-based and source file is unmodified if ( allocated ( target % digest_cached )) then if ( target % digest_cached == target % source % digest ) target % skip = . true . end if elseif ( exists ( target % output_file )) then ! Skip if target is not source-based and already exists target % skip = . true . end if ! Loop over target dependencies target % schedule = 1 do i = 1 , size ( target % dependencies ) ! Sort dependency call sort_target ( target % dependencies ( i )% ptr ) if (. not . target % dependencies ( i )% ptr % skip ) then ! Can't skip target if any dependency is not skipped target % skip = . false . ! Set target schedule after all of its dependencies target % schedule = max ( target % schedule , target % dependencies ( i )% ptr % schedule + 1 ) end if end do ! Mark flag as processed: either sorted or skipped target % sorted = . not . target % skip end subroutine sort_target !> Construct a build schedule from the sorted targets. !> !> The schedule is broken into regions, described by `schedule_ptr`, !> where targets in each region can be compiled in parallel. !> subroutine schedule_targets ( queue , schedule_ptr , targets ) type ( build_target_ptr ), allocatable , intent ( out ) :: queue (:) integer , allocatable :: schedule_ptr (:) type ( build_target_ptr ), intent ( in ) :: targets (:) integer :: i , j integer :: n_schedule , n_sorted n_schedule = 0 ! Number of schedule regions n_sorted = 0 ! Total number of targets to build do i = 1 , size ( targets ) if ( targets ( i )% ptr % sorted ) then n_sorted = n_sorted + 1 end if n_schedule = max ( n_schedule , targets ( i )% ptr % schedule ) end do allocate ( queue ( n_sorted )) allocate ( schedule_ptr ( n_schedule + 1 )) ! Construct the target queue and schedule region pointer n_sorted = 1 schedule_ptr ( n_sorted ) = 1 do i = 1 , n_schedule do j = 1 , size ( targets ) if ( targets ( j )% ptr % sorted ) then if ( targets ( j )% ptr % schedule == i ) then queue ( n_sorted )% ptr => targets ( j )% ptr n_sorted = n_sorted + 1 end if end if end do schedule_ptr ( i + 1 ) = n_sorted end do end subroutine schedule_targets !> Call compile/link command for a single target. !> !> If successful, also caches the source file digest to disk. !> subroutine build_target ( model , target , verbose , stat ) type ( fpm_model_t ), intent ( in ) :: model type ( build_target_t ), intent ( in ), target :: target logical , intent ( in ) :: verbose integer , intent ( out ) :: stat integer :: fh !$omp critical if (. not . exists ( dirname ( target % output_file ))) then call mkdir ( dirname ( target % output_file ), verbose ) end if !$omp end critical select case ( target % target_type ) case ( FPM_TARGET_OBJECT ) call model % compiler % compile_fortran ( target % source % file_name , target % output_file , & & target % compile_flags , target % output_log_file , stat ) case ( FPM_TARGET_C_OBJECT ) call model % compiler % compile_c ( target % source % file_name , target % output_file , & & target % compile_flags , target % output_log_file , stat ) case ( FPM_TARGET_CPP_OBJECT ) call model % compiler % compile_cpp ( target % source % file_name , target % output_file , & & target % compile_flags , target % output_log_file , stat ) case ( FPM_TARGET_EXECUTABLE ) call model % compiler % link ( target % output_file , & & target % compile_flags // \" \" // target % link_flags , target % output_log_file , stat ) case ( FPM_TARGET_ARCHIVE ) call model % archiver % make_archive ( target % output_file , target % link_objects , & & target % output_log_file , stat ) end select if ( stat == 0 . and . allocated ( target % source )) then open ( newunit = fh , file = target % output_file // '.digest' , status = 'unknown' ) write ( fh , * ) target % source % digest close ( fh ) end if end subroutine build_target !> Read and print the build log for target !> subroutine print_build_log ( target ) type ( build_target_t ), intent ( in ), target :: target integer :: fh , ios character (:), allocatable :: line if ( exists ( target % output_log_file )) then open ( newunit = fh , file = target % output_log_file , status = 'old' ) do call getline ( fh , line , ios ) if ( ios /= 0 ) exit write ( * , '(A)' ) trim ( line ) end do close ( fh ) else write ( stderr , '(*(g0:,1x))' ) ' Unable to find build log \"' , basename ( target % output_log_file ), '\"' end if end subroutine print_build_log end module fpm_backend","tags":"","loc":"sourcefile/fpm_backend.f90.html"},{"title":"fortran.f90 – Fortran-lang/fpm","text":"Source Code module fpm_manifest_fortran use fpm_error , only : error_t , syntax_error , fatal_error use fpm_toml , only : toml_table , toml_key , toml_stat , get_value , serializable_t , set_value , set_string implicit none private public :: fortran_config_t , new_fortran_config !> Configuration data for Fortran type , extends ( serializable_t ) :: fortran_config_t !> Enable default implicit typing logical :: implicit_typing = . false . !> Enable implicit external interfaces logical :: implicit_external = . false . !> Form to use for all Fortran sources character (:), allocatable :: source_form contains !> Serialization interface procedure :: serializable_is_same => fortran_is_same procedure :: dump_to_toml procedure :: load_from_toml end type fortran_config_t character ( len =* ), parameter , private :: class_name = 'fortran_config_t' contains !> Construct a new build configuration from a TOML data structure subroutine new_fortran_config ( self , table , error ) !> Instance of the fortran configuration type ( fortran_config_t ), intent ( out ) :: self !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error integer :: stat character (:), allocatable :: source_form call check ( table , error ) if ( allocated ( error )) return call get_value ( table , \"implicit-typing\" , self % implicit_typing , . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'implicit-typing' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"implicit-external\" , self % implicit_external , . false ., stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'implicit-external' in fpm.toml, expecting logical\" ) return end if call get_value ( table , \"source-form\" , source_form , \"free\" , stat = stat ) if ( stat /= toml_stat % success ) then call fatal_error ( error , \"Error while reading value for 'source-form' in fpm.toml, expecting logical\" ) return end if select case ( source_form ) case default call fatal_error ( error , \"Value of source-form cannot be '\" // source_form // \"'\" ) return case ( \"free\" , \"fixed\" , \"default\" ) self % source_form = source_form end select end subroutine new_fortran_config !> Check local schema for allowed entries subroutine check ( table , error ) !> Instance of the TOML data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error type ( toml_key ), allocatable :: list (:) integer :: ikey call table % get_keys ( list ) ! table can be empty if ( size ( list ) < 1 ) return do ikey = 1 , size ( list ) select case ( list ( ikey )% key ) case ( \"implicit-typing\" , \"implicit-external\" , \"source-form\" ) continue case default call syntax_error ( error , \"Key \" // list ( ikey )% key // \" is not allowed in fortran\" ) exit end select end do end subroutine check logical function fortran_is_same ( this , that ) class ( fortran_config_t ), intent ( in ) :: this class ( serializable_t ), intent ( in ) :: that fortran_is_same = . false . select type ( other => that ) type is ( fortran_config_t ) if ( this % implicit_typing . neqv . other % implicit_typing ) return if ( this % implicit_external . neqv . other % implicit_external ) return if (. not . allocated ( this % source_form ). eqv . allocated ( other % source_form )) return if (. not . this % source_form == other % source_form ) return class default ! Not the same type return end select !> All checks passed! fortran_is_same = . true . end function fortran_is_same !> Dump install config to toml table subroutine dump_to_toml ( self , table , error ) !> Instance of the serializable object class ( fortran_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call set_value ( table , \"implicit-typing\" , self % implicit_typing , error , class_name ) if ( allocated ( error )) return call set_value ( table , \"implicit-external\" , self % implicit_external , error , class_name ) if ( allocated ( error )) return call set_string ( table , \"source-form\" , self % source_form , error , class_name ) if ( allocated ( error )) return end subroutine dump_to_toml !> Read install config from toml table (no checks made at this stage) subroutine load_from_toml ( self , table , error ) !> Instance of the serializable object class ( fortran_config_t ), intent ( inout ) :: self !> Data structure type ( toml_table ), intent ( inout ) :: table !> Error handling type ( error_t ), allocatable , intent ( out ) :: error call get_value ( table , \"implicit-typing\" , self % implicit_typing , error , class_name ) if ( allocated ( error )) return call get_value ( table , \"implicit-external\" , self % implicit_external , error , class_name ) if ( allocated ( error )) return call get_value ( table , \"source-form\" , self % source_form ) end subroutine load_from_toml end module fpm_manifest_fortran","tags":"","loc":"sourcefile/fortran.f90.html"},{"title":"fpm.f90 – Fortran-lang/fpm","text":"Source Code module fpm use fpm_strings , only : string_t , operator (. in .), glob , join , string_cat , & lower , str_ends_with , is_fortran_name , str_begins_with_str , & is_valid_module_name , len_trim use fpm_backend , only : build_package use fpm_command_line , only : fpm_build_settings , fpm_new_settings , & fpm_run_settings , fpm_install_settings , fpm_test_settings , & fpm_clean_settings use fpm_dependency , only : new_dependency_tree use fpm_filesystem , only : is_dir , join_path , list_files , exists , & basename , filewrite , mkdir , run , os_delete_dir use fpm_model , only : fpm_model_t , srcfile_t , show_model , fortran_features_t , & FPM_SCOPE_UNKNOWN , FPM_SCOPE_LIB , FPM_SCOPE_DEP , & FPM_SCOPE_APP , FPM_SCOPE_EXAMPLE , FPM_SCOPE_TEST use fpm_compiler , only : new_compiler , new_archiver , set_cpp_preprocessor_flags use fpm_sources , only : add_executable_sources , add_sources_from_dir use fpm_targets , only : targets_from_sources , build_target_t , build_target_ptr , & FPM_TARGET_EXECUTABLE , FPM_TARGET_ARCHIVE use fpm_manifest , only : get_package_data , package_config_t use fpm_meta , only : resolve_metapackages use fpm_error , only : error_t , fatal_error , fpm_stop use fpm_toml , only : name_is_json use , intrinsic :: iso_fortran_env , only : stdin => input_unit , & & stdout => output_unit , & & stderr => error_unit use iso_c_binding , only : c_char , c_ptr , c_int , c_null_char , c_associated , c_f_pointer use fpm_environment , only : os_is_unix use fpm_settings , only : fpm_global_settings , get_global_settings implicit none private public :: cmd_build , cmd_run , cmd_clean public :: build_model , check_modules_for_duplicates contains !> Constructs a valid fpm model from command line settings and the toml manifest. subroutine build_model ( model , settings , package , error ) type ( fpm_model_t ), intent ( out ) :: model class ( fpm_build_settings ), intent ( inout ) :: settings type ( package_config_t ), intent ( inout ) :: package type ( error_t ), allocatable , intent ( out ) :: error integer :: i , j type ( package_config_t ) :: dependency character ( len = :), allocatable :: manifest , lib_dir logical :: has_cpp logical :: duplicates_found type ( string_t ) :: include_dir model % package_name = package % name allocate ( model % include_dirs ( 0 )) allocate ( model % link_libraries ( 0 )) allocate ( model % external_modules ( 0 )) call new_compiler ( model % compiler , settings % compiler , settings % c_compiler , & & settings % cxx_compiler , echo = settings % verbose , verbose = settings % verbose ) call new_archiver ( model % archiver , settings % archiver , & & echo = settings % verbose , verbose = settings % verbose ) if ( model % compiler % is_unknown ()) then write ( * , '(*(a:,1x))' ) & \"\" , \"Unknown compiler\" , model % compiler % fc , \"requested!\" , & \"Defaults for this compiler might be incorrect\" end if call new_compiler_flags ( model , settings ) model % build_prefix = join_path ( \"build\" , basename ( model % compiler % fc )) model % include_tests = settings % build_tests model % enforce_module_names = package % build % module_naming model % module_prefix = package % build % module_prefix ! Resolve meta-dependencies into the package and the model call resolve_metapackages ( model , package , settings , error ) if ( allocated ( error )) return ! Create dependencies call new_dependency_tree ( model % deps , cache = join_path ( \"build\" , \"cache.toml\" )) ! Build and resolve model dependencies call model % deps % add ( package , error ) if ( allocated ( error )) return ! Update dependencies where needed call model % deps % update ( error ) if ( allocated ( error )) return ! build/ directory should now exist if (. not . exists ( \"build/.gitignore\" )) then call filewrite ( join_path ( \"build\" , \".gitignore\" ),[ \"*\" ]) end if allocate ( model % packages ( model % deps % ndep )) has_cpp = . false . do i = 1 , model % deps % ndep associate ( dep => model % deps % dep ( i )) manifest = join_path ( dep % proj_dir , \"fpm.toml\" ) call get_package_data ( dependency , manifest , error , apply_defaults = . true .) if ( allocated ( error )) exit model % packages ( i )% name = dependency % name associate ( features => model % packages ( i )% features ) features % implicit_typing = dependency % fortran % implicit_typing features % implicit_external = dependency % fortran % implicit_external features % source_form = dependency % fortran % source_form end associate model % packages ( i )% version = package % version % s () !> Add this dependency's manifest macros call model % packages ( i )% preprocess % destroy () if ( allocated ( dependency % preprocess )) then do j = 1 , size ( dependency % preprocess ) call model % packages ( i )% preprocess % add_config ( dependency % preprocess ( j )) end do end if !> Add this dependency's package-level macros if ( allocated ( dep % preprocess )) then do j = 1 , size ( dep % preprocess ) call model % packages ( i )% preprocess % add_config ( dep % preprocess ( j )) end do end if if ( model % packages ( i )% preprocess % is_cpp ()) has_cpp = . true . if (. not . allocated ( model % packages ( i )% sources )) allocate ( model % packages ( i )% sources ( 0 )) if ( allocated ( dependency % library )) then if ( allocated ( dependency % library % source_dir )) then lib_dir = join_path ( dep % proj_dir , dependency % library % source_dir ) if ( is_dir ( lib_dir )) then call add_sources_from_dir ( model % packages ( i )% sources , lib_dir , FPM_SCOPE_LIB , & with_f_ext = model % packages ( i )% preprocess % suffixes , error = error ) if ( allocated ( error )) exit end if end if if ( allocated ( dependency % library % include_dir )) then do j = 1 , size ( dependency % library % include_dir ) include_dir % s = join_path ( dep % proj_dir , dependency % library % include_dir ( j )% s ) if ( is_dir ( include_dir % s )) then model % include_dirs = [ model % include_dirs , include_dir ] end if end do end if end if if ( allocated ( dependency % build % link )) then model % link_libraries = [ model % link_libraries , dependency % build % link ] end if if ( allocated ( dependency % build % external_modules )) then model % external_modules = [ model % external_modules , dependency % build % external_modules ] end if ! Copy naming conventions from this dependency's manifest model % packages ( i )% enforce_module_names = dependency % build % module_naming model % packages ( i )% module_prefix = dependency % build % module_prefix end associate end do if ( allocated ( error )) return ! Add optional flags if ( has_cpp ) call set_cpp_preprocessor_flags ( model % compiler % id , model % fortran_compile_flags ) ! Add sources from executable directories if ( is_dir ( 'app' ) . and . package % build % auto_executables ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'app' , FPM_SCOPE_APP , & with_executables = . true ., with_f_ext = model % packages ( 1 )% preprocess % suffixes ,& error = error ) if ( allocated ( error )) then return end if end if if ( is_dir ( 'example' ) . and . package % build % auto_examples ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'example' , FPM_SCOPE_EXAMPLE , & with_executables = . true ., & with_f_ext = model % packages ( 1 )% preprocess % suffixes , error = error ) if ( allocated ( error )) then return end if end if if ( is_dir ( 'test' ) . and . package % build % auto_tests ) then call add_sources_from_dir ( model % packages ( 1 )% sources , 'test' , FPM_SCOPE_TEST , & with_executables = . true ., & with_f_ext = model % packages ( 1 )% preprocess % suffixes , error = error ) if ( allocated ( error )) then return endif end if if ( allocated ( package % executable )) then call add_executable_sources ( model % packages ( 1 )% sources , package % executable , FPM_SCOPE_APP , & auto_discover = package % build % auto_executables , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return end if end if if ( allocated ( package % example )) then call add_executable_sources ( model % packages ( 1 )% sources , package % example , FPM_SCOPE_EXAMPLE , & auto_discover = package % build % auto_examples , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return end if end if if ( allocated ( package % test )) then call add_executable_sources ( model % packages ( 1 )% sources , package % test , FPM_SCOPE_TEST , & auto_discover = package % build % auto_tests , & with_f_ext = model % packages ( 1 )% preprocess % suffixes , & error = error ) if ( allocated ( error )) then return endif endif if ( settings % verbose ) then write ( * , * ) ' BUILD_NAME: ' , model % build_prefix write ( * , * ) ' COMPILER: ' , model % compiler % fc write ( * , * ) ' C COMPILER: ' , model % compiler % cc write ( * , * ) ' CXX COMPILER: ' , model % compiler % cxx write ( * , * ) ' COMPILER OPTIONS: ' , model % fortran_compile_flags write ( * , * ) ' C COMPILER OPTIONS: ' , model % c_compile_flags write ( * , * ) ' CXX COMPILER OPTIONS: ' , model % cxx_compile_flags write ( * , * ) ' LINKER OPTIONS: ' , model % link_flags write ( * , * ) ' INCLUDE DIRECTORIES: [' , string_cat ( model % include_dirs , ',' ), ']' end if ! Check for invalid module names call check_module_names ( model , error ) if ( allocated ( error )) return ! Check for duplicate modules duplicates_found = . false . call check_modules_for_duplicates ( model , duplicates_found ) if ( duplicates_found ) then call fpm_stop ( 1 , '*build_model*:Error: One or more duplicate module names found.' ) end if end subroutine build_model !> Initialize model compiler flags subroutine new_compiler_flags ( model , settings ) type ( fpm_model_t ), intent ( inout ) :: model type ( fpm_build_settings ), intent ( in ) :: settings character ( len = :), allocatable :: flags , cflags , cxxflags , ldflags if ( settings % flag == '' ) then flags = model % compiler % get_default_flags ( settings % profile == \"release\" ) else flags = settings % flag select case ( settings % profile ) case ( \"release\" , \"debug\" ) flags = flags // model % compiler % get_default_flags ( settings % profile == \"release\" ) end select end if cflags = trim ( settings % cflag ) cxxflags = trim ( settings % cxxflag ) ldflags = trim ( settings % ldflag ) model % fortran_compile_flags = flags model % c_compile_flags = cflags model % cxx_compile_flags = cxxflags model % link_flags = ldflags end subroutine new_compiler_flags ! Check for duplicate modules subroutine check_modules_for_duplicates ( model , duplicates_found ) type ( fpm_model_t ), intent ( in ) :: model integer :: maxsize integer :: i , j , k , l , m , modi type ( string_t ), allocatable :: modules (:) logical :: duplicates_found ! Initialise the size of array maxsize = 0 ! Get number of modules provided by each source file of every package do i = 1 , size ( model % packages ) do j = 1 , size ( model % packages ( i )% sources ) if ( allocated ( model % packages ( i )% sources ( j )% modules_provided )) then maxsize = maxsize + size ( model % packages ( i )% sources ( j )% modules_provided ) end if end do end do ! Allocate array to contain distinct names of modules allocate ( modules ( maxsize )) ! Initialise index to point at start of the newly allocated array modi = 1 ! Loop through modules provided by each source file of every package ! Add it to the array if it is not already there ! Otherwise print out warning about duplicates do k = 1 , size ( model % packages ) do l = 1 , size ( model % packages ( k )% sources ) if ( allocated ( model % packages ( k )% sources ( l )% modules_provided )) then do m = 1 , size ( model % packages ( k )% sources ( l )% modules_provided ) if ( model % packages ( k )% sources ( l )% modules_provided ( m )% s . in . modules (: modi - 1 )) then write ( stderr , * ) \"Warning: Module \" , model % packages ( k )% sources ( l )% modules_provided ( m )% s , & \" in \" , model % packages ( k )% sources ( l )% file_name , \" is a duplicate\" duplicates_found = . true . else modules ( modi ) = model % packages ( k )% sources ( l )% modules_provided ( m ) modi = modi + 1 end if end do end if end do end do end subroutine check_modules_for_duplicates ! Check names of all modules in this package and its dependencies subroutine check_module_names ( model , error ) type ( fpm_model_t ), intent ( in ) :: model type ( error_t ), allocatable , intent ( out ) :: error integer :: k , l , m logical :: valid , errors_found , enforce_this_file type ( string_t ) :: package_name , module_name , package_prefix errors_found = . false . ! Loop through modules provided by each source file of every package ! Add it to the array if it is not already there ! Otherwise print out warning about duplicates do k = 1 , size ( model % packages ) package_name = string_t ( model % packages ( k )% name ) ! Custom prefix is taken from each dependency's manifest if ( model % packages ( k )% enforce_module_names ) then package_prefix = model % packages ( k )% module_prefix else package_prefix = string_t ( \"\" ) end if ! Warn the user if some of the dependencies have loose naming if ( model % enforce_module_names . and . . not . model % packages ( k )% enforce_module_names ) then write ( stderr , * ) \"Warning: Dependency \" , package_name % s // & \" does not enforce module naming, but project does. \" end if do l = 1 , size ( model % packages ( k )% sources ) ! Module naming is not enforced in test modules enforce_this_file = model % enforce_module_names . and . & model % packages ( k )% sources ( l )% unit_scope /= FPM_SCOPE_TEST if ( allocated ( model % packages ( k )% sources ( l )% modules_provided )) then do m = 1 , size ( model % packages ( k )% sources ( l )% modules_provided ) module_name = model % packages ( k )% sources ( l )% modules_provided ( m ) valid = is_valid_module_name ( module_name , & package_name , & package_prefix , & enforce_this_file ) if (. not . valid ) then if ( enforce_this_file ) then if ( len_trim ( package_prefix ) > 0 ) then write ( stderr , * ) \"ERROR: Module \" , module_name % s , & \" in \" , model % packages ( k )% sources ( l )% file_name , & \" does not match its package name (\" // package_name % s // & \") or custom prefix (\" // package_prefix % s // \").\" else write ( stderr , * ) \"ERROR: Module \" , module_name % s , & \" in \" , model % packages ( k )% sources ( l )% file_name , & \" does not match its package name (\" // package_name % s // \").\" endif else write ( stderr , * ) \"ERROR: Module \" , module_name % s , & \" in \" , model % packages ( k )% sources ( l )% file_name , & \" has an invalid Fortran name. \" end if errors_found = . true . end if end do end if end do end do if ( errors_found ) then if ( model % enforce_module_names ) & write ( stderr , * ) \" Hint: Try disabling module naming in the manifest: [build] module-naming=false . \" call fatal_error ( error , \"The package contains invalid module names. \" // & \"Naming conventions \" // merge ( 'are' , 'not' , model % enforce_module_names ) // & \" being requested.\" ) end if end subroutine check_module_names subroutine cmd_build ( settings ) type ( fpm_build_settings ), intent ( inout ) :: settings type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( error_t ), allocatable :: error integer :: i call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Package error: ' // error % message ) end if call build_model ( model , settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Model error: ' // error % message ) end if call targets_from_sources ( targets , model , settings % prune , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_build* Target error: ' // error % message ) end if !> Dump model to file if ( len_trim ( settings % dump ) > 0 ) then call model % dump ( trim ( settings % dump ), error , json = name_is_json ( trim ( settings % dump ))) if ( allocated ( error )) call fpm_stop ( 1 , '*cmd_build* Model dump error: ' // error % message ) endif if ( settings % list ) then do i = 1 , size ( targets ) write ( stderr , * ) targets ( i )% ptr % output_file enddo else if ( settings % show_model ) then call show_model ( model ) else call build_package ( targets , model , verbose = settings % verbose ) endif end subroutine cmd_build subroutine cmd_run ( settings , test ) class ( fpm_run_settings ), intent ( inout ) :: settings logical , intent ( in ) :: test integer :: i , j , col_width logical :: found ( size ( settings % name )) type ( error_t ), allocatable :: error type ( package_config_t ) :: package type ( fpm_model_t ) :: model type ( build_target_ptr ), allocatable :: targets (:) type ( string_t ) :: exe_cmd type ( string_t ), allocatable :: executables (:) type ( build_target_t ), pointer :: exe_target type ( srcfile_t ), pointer :: exe_source integer :: run_scope , firsterror integer , allocatable :: stat (:), target_ID (:) character ( len = :), allocatable :: line call get_package_data ( package , \"fpm.toml\" , error , apply_defaults = . true .) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Package error: ' // error % message ) end if call build_model ( model , settings , package , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Model error: ' // error % message ) end if call targets_from_sources ( targets , model , settings % prune , error ) if ( allocated ( error )) then call fpm_stop ( 1 , '*cmd_run* Targets error: ' // error % message ) end if if ( test ) then run_scope = FPM_SCOPE_TEST else run_scope = merge ( FPM_SCOPE_EXAMPLE , FPM_SCOPE_APP , settings % example ) end if ! Enumerate executable targets to run col_width = - 1 found (:) = . false . allocate ( executables ( size ( targets )), target_ID ( size ( targets ))) enumerate : do i = 1 , size ( targets ) exe_target => targets ( i )% ptr if ( should_be_run ( settings , run_scope , exe_target )) then exe_source => exe_target % dependencies ( 1 )% ptr % source col_width = max ( col_width , len ( basename ( exe_target % output_file )) + 2 ) ! Priority by name ID, or 0 if no name present (run first) j = settings % name_ID ( exe_source % exe_name ) target_ID ( i ) = j if ( j > 0 ) found ( j ) = . true . exe_cmd % s = exe_target % output_file executables ( i ) = exe_cmd else target_ID ( i ) = huge ( target_ID ( i )) endif end do enumerate ! sort executables by ascending name ID, resize call sort_executables ( target_ID , executables ) ! Check if any apps/tests were found if ( col_width < 0 ) then if ( test ) then call fpm_stop ( 0 , 'No tests to run' ) else call fpm_stop ( 0 , 'No executables to run' ) end if end if ! Check all names are valid ! or no name and found more than one file if ( any (. not . found ) ) then line = join ( settings % name ) if ( line /= '.' ) then ! do not report these special strings if ( any (. not . found )) then write ( stderr , '(A)' , advance = \"no\" ) '*cmd_run*:specified names ' do j = 1 , size ( settings % name ) if (. not . found ( j )) write ( stderr , '(A)' , advance = \"no\" ) '\"' // trim ( settings % name ( j )) // '\" ' end do write ( stderr , '(A)' ) 'not found.' write ( stderr , * ) else if ( settings % verbose ) then write ( stderr , '(A)' , advance = \"yes\" ) 'when more than one executable is available' write ( stderr , '(A)' , advance = \"yes\" ) ' program names must be specified.' endif endif call compact_list_all () if ( line == '.' . or . line == ' ' ) then ! do not report these special strings call fpm_stop ( 0 , '' ) else call fpm_stop ( 1 , '' ) endif end if call build_package ( targets , model , verbose = settings % verbose ) if ( settings % list ) then call compact_list () else allocate ( stat ( size ( executables ))) do i = 1 , size ( executables ) if ( exists ( executables ( i )% s )) then if ( settings % runner /= ' ' ) then if (. not . allocated ( settings % args )) then call run ( settings % runner_command () // ' ' // executables ( i )% s , & echo = settings % verbose , exitstat = stat ( i )) else call run ( settings % runner_command () // ' ' // executables ( i )% s // \" \" // settings % args , & echo = settings % verbose , exitstat = stat ( i )) endif else if (. not . allocated ( settings % args )) then call run ( executables ( i )% s , echo = settings % verbose , exitstat = stat ( i )) else call run ( executables ( i )% s // \" \" // settings % args , echo = settings % verbose , & exitstat = stat ( i )) endif endif else call fpm_stop ( 1 , '*cmd_run*:' // executables ( i )% s // ' not found' ) end if end do if ( any ( stat /= 0 )) then do i = 1 , size ( stat ) if ( stat ( i ) /= 0 ) then write ( stderr , '(*(g0:,1x))' ) ' Execution for object \"' , basename ( executables ( i )% s ),& '\" returned exit code ' , stat ( i ) end if end do firsterror = findloc ( stat /= 0 , value = . true ., dim = 1 ) call fpm_stop ( stat ( firsterror ), '*cmd_run*:stopping due to failed executions' ) end if end if contains subroutine compact_list_all () integer , parameter :: LINE_WIDTH = 80 integer :: ii , jj , nCol jj = 1 nCol = LINE_WIDTH / col_width write ( stderr , * ) 'Available names:' do ii = 1 , size ( targets ) exe_target => targets ( ii )% ptr if ( exe_target % target_type == FPM_TARGET_EXECUTABLE . and . & allocated ( exe_target % dependencies )) then exe_source => exe_target % dependencies ( 1 )% ptr % source if ( exe_source % unit_scope == run_scope ) then write ( stderr , '(A)' , advance = ( merge ( \"yes\" , \"no \" , modulo ( jj , nCol ) == 0 ))) & & [ character ( len = col_width ) :: basename ( exe_target % output_file , suffix = . false .)] jj = jj + 1 end if end if end do write ( stderr , * ) end subroutine compact_list_all subroutine compact_list () integer , parameter :: LINE_WIDTH = 80 integer :: ii , jj , nCol jj = 1 nCol = LINE_WIDTH / col_width write ( stderr , * ) 'Matched names:' do ii = 1 , size ( executables ) write ( stderr , '(A)' , advance = ( merge ( \"yes\" , \"no \" , modulo ( jj , nCol ) == 0 ))) & & [ character ( len = col_width ) :: basename ( executables ( ii )% s , suffix = . false .)] jj = jj + 1 end do write ( stderr , * ) end subroutine compact_list end subroutine cmd_run subroutine delete_skip ( is_unix ) !> delete directories in the build folder, skipping dependencies logical , intent ( in ) :: is_unix character ( len = :), allocatable :: dir type ( string_t ), allocatable :: files (:) integer :: i call list_files ( 'build' , files , . false .) do i = 1 , size ( files ) if ( is_dir ( files ( i )% s )) then dir = files ( i )% s if (. not . str_ends_with ( dir , 'dependencies' )) call os_delete_dir ( is_unix , dir ) end if end do end subroutine delete_skip !> Delete the build directory including or excluding dependencies. Can be used !> to clear the registry cache. subroutine cmd_clean ( settings ) !> Settings for the clean command. class ( fpm_clean_settings ), intent ( in ) :: settings character :: user_response type ( fpm_global_settings ) :: global_settings type ( error_t ), allocatable :: error ! Clear registry cache if ( settings % registry_cache ) then call get_global_settings ( global_settings , error ) if ( allocated ( error )) return call os_delete_dir ( os_is_unix (), global_settings % registry_settings % cache_path ) end if if ( is_dir ( 'build' )) then ! Remove the entire build directory if ( settings % clean_all ) then call os_delete_dir ( os_is_unix (), 'build' ); return ! Remove the build directory but skip dependencies else if ( settings % clean_skip ) then call delete_skip ( os_is_unix ()); return end if ! Prompt to remove the build directory but skip dependencies write ( stdout , '(A)' , advance = 'no' ) \"Delete build, excluding dependencies (y/n)? \" read ( stdin , '(A1)' ) user_response if ( lower ( user_response ) == 'y' ) call delete_skip ( os_is_unix ()) else write ( stdout , '(A)' ) \"fpm: No build directory found.\" end if end subroutine cmd_clean !> Sort executables by namelist ID, and trim unused values pure subroutine sort_executables ( target_ID , executables ) integer , allocatable , intent ( inout ) :: target_ID (:) type ( string_t ), allocatable , intent ( inout ) :: executables (:) integer :: i , j , n , used n = size ( target_ID ) used = 0 sort : do i = 1 , n do j = i + 1 , n if ( target_ID ( j ) < target_ID ( i )) & call swap ( target_ID ( i ), target_ID ( j ), executables ( i ), executables ( j )) end do if ( target_ID ( i ) < huge ( target_ID ( i ))) used = i end do sort if ( used > 0 . and . used < n ) then target_ID = target_ID ( 1 : used ) executables = executables ( 1 : used ) end if contains elemental subroutine swap ( t1 , t2 , e1 , e2 ) integer , intent ( inout ) :: t1 , t2 type ( string_t ), intent ( inout ) :: e1 , e2 integer :: tmp type ( string_t ) :: etmp tmp = t1 t1 = t2 t2 = tmp etmp = e1 e1 = e2 e2 = etmp end subroutine swap end subroutine sort_executables !> Check if an executable should be run logical function should_be_run ( settings , run_scope , exe_target ) class ( fpm_run_settings ), intent ( in ) :: settings integer , intent ( in ) :: run_scope type ( build_target_t ), intent ( in ) :: exe_target integer :: j if ( exe_target % is_executable_target ( run_scope )) then associate ( exe_source => exe_target % dependencies ( 1 )% ptr % source ) if ( exe_source % unit_scope /= run_scope ) then ! Other scope should_be_run = . false . elseif ( size ( settings % name ) == 0 . or . settings % list ) then ! Run all or list all should_be_run = . true . else ! Is found in list should_be_run = settings % name_ID ( exe_source % exe_name ) > 0 end if end associate else !> Invalid target should_be_run = . false . endif end function should_be_run end module fpm","tags":"","loc":"sourcefile/fpm.f90.html"},{"title":"fpm_filesystem.F90 – Fortran-lang/fpm","text":"Source Code !> This module contains general routines for interacting with the file system !! module fpm_filesystem use , intrinsic :: iso_fortran_env , only : stdin => input_unit , stdout => output_unit , stderr => error_unit use , intrinsic :: iso_c_binding , only : c_new_line use fpm_environment , only : get_os_type , & OS_UNKNOWN , OS_LINUX , OS_MACOS , OS_WINDOWS , & OS_CYGWIN , OS_SOLARIS , OS_FREEBSD , OS_OPENBSD use fpm_environment , only : separator , get_env , os_is_unix use fpm_strings , only : f_string , replace , string_t , split , split_first_last , dilate , str_begins_with_str use iso_c_binding , only : c_char , c_ptr , c_int , c_null_char , c_associated , c_f_pointer use fpm_error , only : fpm_stop , error_t , fatal_error implicit none private public :: basename , canon_path , dirname , is_dir , join_path , number_of_rows , list_files , get_local_prefix , & mkdir , exists , get_temp_filename , windows_path , unix_path , getline , delete_file , fileopen , fileclose , & filewrite , warnwrite , parent_dir , is_hidden_file , read_lines , read_lines_expanded , which , run , & os_delete_dir , is_absolute_path , get_home , execute_and_read_output , get_dos_path #ifndef FPM_BOOTSTRAP interface function c_opendir ( dir ) result ( r ) bind ( c , name = \"c_opendir\" ) import c_char , c_ptr character ( kind = c_char ), intent ( in ) :: dir ( * ) type ( c_ptr ) :: r end function c_opendir function c_readdir ( dir ) result ( r ) bind ( c , name = \"c_readdir\" ) import c_ptr type ( c_ptr ), intent ( in ), value :: dir type ( c_ptr ) :: r end function c_readdir function c_closedir ( dir ) result ( r ) bind ( c , name = \"closedir\" ) import c_ptr , c_int type ( c_ptr ), intent ( in ), value :: dir integer ( kind = c_int ) :: r end function c_closedir function c_get_d_name ( dir ) result ( r ) bind ( c , name = \"get_d_name\" ) import c_ptr type ( c_ptr ), intent ( in ), value :: dir type ( c_ptr ) :: r end function c_get_d_name function c_is_dir ( path ) result ( r ) bind ( c , name = \"c_is_dir\" ) import c_char , c_int character ( kind = c_char ), intent ( in ) :: path ( * ) integer ( kind = c_int ) :: r end function c_is_dir end interface #endif character ( * ), parameter :: eol = new_line ( 'a' ) !! End of line contains !> Extract filename from path with/without suffix function basename ( path , suffix ) result ( base ) character ( * ), intent ( In ) :: path logical , intent ( in ), optional :: suffix character (:), allocatable :: base character (:), allocatable :: file_parts (:) logical :: with_suffix if (. not . present ( suffix )) then with_suffix = . true . else with_suffix = suffix end if call split ( path , file_parts , delimiters = '\\/' ) if ( size ( file_parts ) > 0 ) then base = trim ( file_parts ( size ( file_parts ))) else base = '' endif if (. not . with_suffix ) then call split ( base , file_parts , delimiters = '.' ) if ( size ( file_parts ) >= 2 ) then base = trim ( file_parts ( size ( file_parts ) - 1 )) endif endif end function basename !> Canonicalize path for comparison !! * Handles path string redundancies !! * Does not test existence of path !! !! To be replaced by realpath/_fullname in stdlib_os !! !! FIXME: Lot's of ugly hacks following here function canon_path ( path ) character ( len =* ), intent ( in ) :: path character ( len = :), allocatable :: canon_path character ( len = :), allocatable :: nixpath integer :: istart , iend , nn , last logical :: is_path , absolute nixpath = unix_path ( path ) istart = 0 nn = 0 iend = 0 absolute = nixpath ( 1 : 1 ) == \"/\" if ( absolute ) then canon_path = \"/\" else canon_path = \"\" end if do while ( iend < len ( nixpath )) call next ( nixpath , istart , iend , is_path ) if ( is_path ) then select case ( nixpath ( istart : iend )) case ( \".\" , \"\" ) ! always drop empty paths case ( \"..\" ) if ( nn > 0 ) then last = scan ( canon_path (: len ( canon_path ) - 1 ), \"/\" , back = . true .) canon_path = canon_path (: last ) nn = nn - 1 else if (. not . absolute ) then canon_path = canon_path // nixpath ( istart : iend ) // \"/\" end if end if case default nn = nn + 1 canon_path = canon_path // nixpath ( istart : iend ) // \"/\" end select end if end do if ( len ( canon_path ) == 0 ) canon_path = \".\" if ( len ( canon_path ) > 1 . and . canon_path ( len ( canon_path ):) == \"/\" ) then canon_path = canon_path (: len ( canon_path ) - 1 ) end if contains subroutine next ( string , istart , iend , is_path ) character ( len =* ), intent ( in ) :: string integer , intent ( inout ) :: istart integer , intent ( inout ) :: iend logical , intent ( inout ) :: is_path integer :: ii , nn character :: tok nn = len ( string ) if ( iend >= nn ) then istart = nn iend = nn return end if ii = min ( iend + 1 , nn ) tok = string ( ii : ii ) is_path = tok /= '/' if (. not . is_path ) then is_path = . false . istart = ii iend = ii return end if istart = ii do ii = min ( iend + 1 , nn ), nn tok = string ( ii : ii ) select case ( tok ) case ( '/' ) exit case default iend = ii cycle end select end do end subroutine next end function canon_path !> Extract dirname from path function dirname ( path ) result ( dir ) character ( * ), intent ( in ) :: path character (:), allocatable :: dir dir = path ( 1 : scan ( path , '/\\',back=.true.)) end function dirname !> Extract dirname from path function parent_dir(path) result (dir) character(*), intent(in) :: path character(:), allocatable :: dir dir = path(1:scan(path,' / \\ ',back=.true.)-1) end function parent_dir !> test if a name matches an existing directory path logical function is_dir(dir) character(*), intent(in) :: dir integer :: stat select case (get_os_type()) case (OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD) call run( \"test -d \" // dir , & & exitstat=stat,echo=.false.,verbose=.false.) case (OS_WINDOWS) call run(' cmd / c \"if not exist ' // windows_path(dir) // '\\ exit /B 1\" ', & & exitstat=stat,echo=.false.,verbose=.false.) end select is_dir = (stat == 0) end function is_dir !> test if a file is hidden logical function is_hidden_file(file_basename) result(r) character(*), intent(in) :: file_basename if (len(file_basename) <= 2) then r = .false. else r = str_begins_with_str(file_basename, ' . ') end if end function is_hidden_file !> Construct path by joining strings with os file separator function join_path(a1,a2,a3,a4,a5) result(path) character(len=*), intent(in) :: a1, a2 character(len=*), intent(in), optional :: a3, a4, a5 character(len=:), allocatable :: path character(len=1) :: filesep logical, save :: has_cache = .false. character(len=1), save :: cache = ' / ' !$omp threadprivate(has_cache, cache) if (has_cache) then filesep = cache else select case (get_os_type()) case default filesep = ' / ' case (OS_WINDOWS) filesep = ' \\ ' end select cache = filesep has_cache = .true. end if if (a1 == \"\") then path = a2 else path = a1 // filesep // a2 end if if (present(a3)) then path = path // filesep // a3 else return end if if (present(a4)) then path = path // filesep // a4 else return end if if (present(a5)) then path = path // filesep // a5 else return end if end function join_path !> Determine number or rows in a file given a LUN integer function number_of_rows(s) result(nrows) integer,intent(in)::s integer :: ios rewind(s) nrows = 0 do read(s, *, iostat=ios) if (ios /= 0) exit nrows = nrows + 1 end do rewind(s) end function number_of_rows !> read lines into an array of TYPE(STRING_T) variables expanding tabs function read_lines_expanded(filename) result(lines) character(len=*), intent(in) :: filename type(string_t), allocatable :: lines(:) integer :: i character(len=:), allocatable :: content integer, allocatable :: first(:), last(:) content = read_text_file(filename) if (len(content) == 0) then allocate (lines(0)) return end if call split_first_last(content, eol, first, last) ! TODO: \\r (< macOS X), \\n (>=macOS X/Linux/Unix), \\r\\n (Windows) ! allocate lines from file content string allocate (lines(size(first))) do i = 1, size(first) allocate(lines(i)%s, source=dilate(content(first(i):last(i)))) end do end function read_lines_expanded !> read lines into an array of TYPE(STRING_T) variables function read_lines(filename) result(lines) character(len=*), intent(in) :: filename type(string_t), allocatable :: lines(:) integer :: i character(len=:), allocatable :: content integer, allocatable :: first(:), last(:) content = read_text_file(filename) if (len(content) == 0) then allocate (lines(0)) return end if call split_first_last(content, eol, first, last) ! TODO: \\r (< macOS X), \\n (>=macOS X/Linux/Unix), \\r\\n (Windows) ! allocate lines from file content string allocate (lines(size(first))) do i = 1, size(first) allocate(lines(i)%s, source=content(first(i):last(i))) end do end function read_lines !> read text file into a string function read_text_file(filename) result(string) character(len=*), intent(in) :: filename character(len=:), allocatable :: string integer :: fh, length open (newunit=fh, file=filename, status=' old ', action=' read ', & access=' stream ', form=' unformatted ') inquire (fh, size=length) allocate (character(len=length) :: string) if (length == 0) return read (fh) string close (fh) end function read_text_file !> Create a directory. Create subdirectories as needed subroutine mkdir(dir, echo) character(len=*), intent(in) :: dir logical, intent(in), optional :: echo integer :: stat if (is_dir(dir)) return select case (get_os_type()) case (OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD) call run(' mkdir - p ' // dir, exitstat=stat,echo=echo,verbose=.false.) case (OS_WINDOWS) call run(\"mkdir \" // windows_path(dir), & & echo=echo, exitstat=stat,verbose=.false.) end select if (stat /= 0) then call fpm_stop(1, ' * mkdir * : directory creation failed ') end if end subroutine mkdir #ifndef FPM_BOOTSTRAP !> Get file & directory names in directory `dir` using iso_c_binding. !! !! - File/directory names return are relative to cwd, ie. preprended with `dir` !! - Includes files starting with `.` except current directory and parent directory !! recursive subroutine list_files(dir, files, recurse) character(len=*), intent(in) :: dir type(string_t), allocatable, intent(out) :: files(:) logical, intent(in), optional :: recurse integer :: i type(string_t), allocatable :: dir_files(:) type(string_t), allocatable :: sub_dir_files(:) type(c_ptr) :: dir_handle type(c_ptr) :: dir_entry_c character(len=:,kind=c_char), allocatable :: fortran_name character(len=:), allocatable :: string_fortran integer, parameter :: N_MAX = 256 type(string_t) :: files_tmp(N_MAX) integer(kind=c_int) :: r if (c_is_dir(dir(1:len_trim(dir))//c_null_char) == 0) then allocate (files(0)) return end if dir_handle = c_opendir(dir(1:len_trim(dir))//c_null_char) if (.not. c_associated(dir_handle)) then print *, ' c_opendir () failed ' error stop end if i = 0 allocate(files(0)) do dir_entry_c = c_readdir(dir_handle) if (.not. c_associated(dir_entry_c)) then exit else string_fortran = f_string(c_get_d_name(dir_entry_c)) if ((string_fortran == ' . ' .or. string_fortran == ' .. ')) then cycle end if i = i + 1 if (i > N_MAX) then files = [files, files_tmp] i = 1 end if files_tmp(i)%s = join_path(dir, string_fortran) end if end do r = c_closedir(dir_handle) if (r /= 0) then print *, ' c_closedir () failed ' error stop end if if (i > 0) then files = [files, files_tmp(1:i)] end if if (present(recurse)) then if (recurse) then allocate(sub_dir_files(0)) do i=1,size(files) if (c_is_dir(files(i)%s//c_null_char) /= 0) then call list_files(files(i)%s, dir_files, recurse=.true.) sub_dir_files = [sub_dir_files, dir_files] end if end do files = [files, sub_dir_files] end if end if end subroutine list_files #else !> Get file & directory names in directory `dir`. !! !! - File/directory names return are relative to cwd, ie. preprended with `dir` !! - Includes files starting with `.` except current directory and parent directory !! recursive subroutine list_files(dir, files, recurse) character(len=*), intent(in) :: dir type(string_t), allocatable, intent(out) :: files(:) logical, intent(in), optional :: recurse integer :: stat, fh, i character(:), allocatable :: temp_file type(string_t), allocatable :: dir_files(:) type(string_t), allocatable :: sub_dir_files(:) if (.not. is_dir(dir)) then allocate (files(0)) return end if allocate (temp_file, source=get_temp_filename()) select case (get_os_type()) case (OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD) call run(' ls - A ' // dir , & & redirect=temp_file, exitstat=stat,echo=.false.,verbose=.false.) case (OS_WINDOWS) call run(' dir / b ' // windows_path(dir), & & redirect=temp_file, exitstat=stat,echo=.false.,verbose=.false.) end select if (stat /= 0) then call fpm_stop(2,' * list_files * : directory listing failed ') end if files = read_lines(temp_file) call delete_file(temp_file) do i=1,size(files) files(i)%s = join_path(dir,files(i)%s) end do if (present(recurse)) then if (recurse) then allocate(sub_dir_files(0)) do i=1,size(files) if (is_dir(files(i)%s)) then call list_files(files(i)%s, dir_files, recurse=.true.) sub_dir_files = [sub_dir_files, dir_files] end if end do files = [files, sub_dir_files] end if end if end subroutine list_files #endif !> test if pathname already exists logical function exists(filename) result(r) character(len=*), intent(in) :: filename inquire(file=filename, exist=r) !> Directories are not files for the Intel compilers. If so, also use this compiler-dependent extension #if defined(__INTEL_COMPILER) if (.not.r) inquire(directory=filename, exist=r) #endif end function !> Get a unused temporary filename !! Calls posix ' tempnam ' - not recommended, but !! we have no security concerns for this application !! and use here is temporary. !! Works with MinGW function get_temp_filename() result(tempfile) ! use iso_c_binding, only: c_ptr, C_NULL_PTR, c_f_pointer integer, parameter :: MAX_FILENAME_LENGTH = 32768 character(:), allocatable :: tempfile type(c_ptr) :: c_tempfile_ptr character(len=1), pointer :: c_tempfile(:) interface function c_tempnam(dir,pfx) result(tmp) bind(c,name=\"tempnam\") import type(c_ptr), intent(in), value :: dir type(c_ptr), intent(in), value :: pfx type(c_ptr) :: tmp end function c_tempnam subroutine c_free(ptr) BIND(C,name=\"free\") import type(c_ptr), value :: ptr end subroutine c_free end interface c_tempfile_ptr = c_tempnam(C_NULL_PTR, C_NULL_PTR) call c_f_pointer(c_tempfile_ptr,c_tempfile,[MAX_FILENAME_LENGTH]) tempfile = f_string(c_tempfile) call c_free(c_tempfile_ptr) end function get_temp_filename !> Replace file system separators for windows function windows_path(path) result(winpath) character(*), intent(in) :: path character(:), allocatable :: winpath integer :: idx winpath = path idx = index(winpath,' / ') do while(idx > 0) winpath(idx:idx) = ' \\ ' idx = index(winpath,' / ') end do end function windows_path !> Replace file system separators for unix function unix_path(path) result(nixpath) character(*), intent(in) :: path character(:), allocatable :: nixpath integer :: idx nixpath = path idx = index(nixpath,' \\ ') do while(idx > 0) nixpath(idx:idx) = ' / ' idx = index(nixpath,' \\ ') end do end function unix_path !>AUTHOR: fpm(1) contributors !!LICENSE: MIT !> !!##NAME !! getline(3f) - [M_io:READ] read a line of arbintrary length from specified !! LUN into allocatable string (up to system line length limit) !! (LICENSE:PD) !! !!##SYNTAX !! subroutine getline(unit,line,iostat,iomsg) !! !! integer,intent(in) :: unit !! character(len=:),allocatable,intent(out) :: line !! integer,intent(out) :: iostat !! character(len=:), allocatable, optional :: iomsg !! !!##DESCRIPTION !! Read a line of any length up to programming environment maximum !! line length. Requires Fortran 2003+. !! !! It is primarily expected to be used when reading input which will !! then be parsed or echoed. !! !! The input file must have a PAD attribute of YES for the function !! to work properly, which is typically true. !! !! The simple use of a loop that repeatedly re-allocates a character !! variable in addition to reading the input file one buffer at a !! time could (depending on the programming environment used) be !! inefficient, as it could reallocate and allocate memory used for !! the output string with each buffer read. !! !!##OPTIONS !! LINE The line read when IOSTAT returns as zero. !! LUN LUN (Fortran logical I/O unit) number of file open and ready !! to read. !! IOSTAT status returned by READ(IOSTAT=IOS). If not zero, an error !! occurred or an end-of-file or end-of-record was encountered. !! IOMSG error message returned by system when IOSTAT is not zero. !! !!##EXAMPLE !! !! Sample program: !! !! program demo_getline !! use,intrinsic :: iso_fortran_env, only : stdin=>input_unit !! use,intrinsic :: iso_fortran_env, only : iostat_end !! use FPM_filesystem, only : getline !! implicit none !! integer :: iostat !! character(len=:),allocatable :: line, iomsg !! open(unit=stdin,pad=' yes ') !! INFINITE: do !! call getline(stdin,line,iostat,iomsg) !! if(iostat /= 0) exit INFINITE !! write(*,' ( a ) ')' [ '//line//' ] ' !! enddo INFINITE !! if(iostat /= iostat_end)then !! write(*,*)' error reading input : ',iomsg !! endif !! end program demo_getline !! subroutine getline(unit, line, iostat, iomsg) !> Formatted IO unit integer, intent(in) :: unit !> Line to read character(len=:), allocatable, intent(out) :: line !> Status of operation integer, intent(out) :: iostat !> Error message character(len=:), allocatable, optional :: iomsg integer, parameter :: BUFFER_SIZE = 1024 character(len=BUFFER_SIZE) :: buffer character(len=256) :: msg integer :: size integer :: stat allocate(character(len=0) :: line) do read(unit, ' ( a ) ', advance=' no ', iostat=stat, iomsg=msg, size=size) & & buffer if (stat > 0) exit line = line // buffer(:size) if (stat < 0) then if (is_iostat_eor(stat)) then stat = 0 end if exit end if end do if (stat /= 0) then if (present(iomsg)) iomsg = trim(msg) end if iostat = stat end subroutine getline !> delete a file by filename subroutine delete_file(file) character(len=*), intent(in) :: file logical :: exist integer :: unit inquire(file=file, exist=exist) if (exist) then open(file=file, newunit=unit) close(unit, status=\"delete\") end if end subroutine delete_file !> write trimmed character data to a file if it does not exist subroutine warnwrite(fname,data) character(len=*),intent(in) :: fname character(len=*),intent(in) :: data(:) if(.not.exists(fname))then call filewrite(fname,data) else write(stderr,' ( * ( g0 , 1 x )) ')' < INFO > ',fname,& & ' already exists . Not overwriting ' endif end subroutine warnwrite !> procedure to open filename as a sequential \"text\" file subroutine fileopen(filename,lun,ier) character(len=*),intent(in) :: filename integer,intent(out) :: lun integer,intent(out),optional :: ier integer :: ios character(len=256) :: message message=' ' ios=0 if(filename/=' ')then open(file=filename, & & newunit=lun, & & form=' formatted ', & ! FORM = FORMATTED | UNFORMATTED & access=' sequential ', & ! ACCESS = SEQUENTIAL| DIRECT | STREAM & action=' write ', & ! ACTION = READ|WRITE| READWRITE & position=' rewind ', & ! POSITION= ASIS | REWIND | APPEND & status=' new ', & ! STATUS = NEW| REPLACE| OLD| SCRATCH| UNKNOWN & iostat=ios, & & iomsg=message) else lun=stdout ios=0 endif if(ios/=0)then lun=-1 if(present(ier))then ier=ios else call fpm_stop(3,' * fileopen * : '//filename//' : '//trim(message)) endif endif end subroutine fileopen !> simple close of a LUN. On error show message and stop (by default) subroutine fileclose(lun,ier) integer,intent(in) :: lun integer,intent(out),optional :: ier character(len=256) :: message integer :: ios if(lun/=-1)then close(unit=lun,iostat=ios,iomsg=message) if(ios/=0)then if(present(ier))then ier=ios else call fpm_stop(4,' * fileclose * : '//trim(message)) endif endif endif end subroutine fileclose !> procedure to write filedata to file filename subroutine filewrite(filename,filedata) character(len=*),intent(in) :: filename character(len=*),intent(in) :: filedata(:) integer :: lun, i, ios character(len=256) :: message call fileopen(filename,lun) if(lun/=-1)then ! program currently stops on error on open, but might ! want it to continue so -1 (unallowed LUN) indicates error ! write file do i=1,size(filedata) write(lun,' ( a ) ',iostat=ios,iomsg=message)trim(filedata(i)) if(ios/=0)then call fpm_stop(5,' * filewrite * : '//filename//' : '//trim(message)) endif enddo endif ! close file call fileclose(lun) end subroutine filewrite !>AUTHOR: John S. Urban !!LICENSE: Public Domain !> !!##Name !! which(3f) - [M_io:ENVIRONMENT] given a command name find the pathname by searching !! the directories in the environment variable $PATH !! (LICENSE:PD) !! !!##Syntax !! function which(command) result(pathname) !! !! character(len=*),intent(in) :: command !! character(len=:),allocatable :: pathname !! !!##Description !! Given a command name find the first file with that name in the directories !! specified by the environment variable $PATH. !! !!##options !! COMMAND the command to search for !! !!##Returns !! PATHNAME the first pathname found in the current user path. Returns blank !! if the command is not found. !! !!##Example !! !! Sample program: !! !! Checking the error message and counting lines: !! !! program demo_which !! use M_io, only : which !! implicit none !! write(*,*)' ls is ',which(' ls ') !! write(*,*)' dir is ',which(' dir ') !! write(*,*)' install is ',which(' install ') !! end program demo_which !! function which(command) result(pathname) character(len=*),intent(in) :: command character(len=:),allocatable :: pathname, checkon, paths(:), exts(:) integer :: i, j pathname='' call split(get_env(' PATH '),paths,delimiters=merge(' ; ',' : ',separator()==' \\ ')) SEARCH: do i=1,size(paths) checkon=trim(join_path(trim(paths(i)),command)) select case(separator()) case(' / ') if(exists(checkon))then pathname=checkon exit SEARCH endif case(' \\ ') if(exists(checkon))then pathname=checkon exit SEARCH endif if(exists(checkon//' . bat '))then pathname=checkon//' . bat ' exit SEARCH endif if(exists(checkon//' . exe '))then pathname=checkon//' . exe ' exit SEARCH endif call split(get_env(' PATHEXT '),exts,delimiters=' ; ') do j=1,size(exts) if(exists(checkon//' . '//trim(exts(j))))then pathname=checkon//' . '//trim(exts(j)) exit SEARCH endif enddo end select enddo SEARCH end function which !>AUTHOR: fpm(1) contributors !!LICENSE: MIT !> !!##Name !! run(3f) - execute specified system command and selectively echo !! command and output to a file and/or stdout. !! (LICENSE:MIT) !! !!##Syntax !! subroutine run(cmd,echo,exitstat,verbose,redirect) !! !! character(len=*), intent(in) :: cmd !! logical,intent(in),optional :: echo !! integer, intent(out),optional :: exitstat !! logical, intent(in), optional :: verbose !! character(*), intent(in), optional :: redirect !! !!##Description !! Execute the specified system command. Optionally !! !! + echo the command before execution !! + return the system exit status of the command. !! + redirect the output of the command to a file. !! + echo command output to stdout !! !! Calling run(3f) is preferred to direct calls to !! execute_command_line(3f) in the fpm(1) source to provide a standard !! interface where output modes can be specified. !! !!##Options !! CMD System command to execute !! ECHO Whether to echo the command being executed or not !! Defaults to .TRUE. . !! VERBOSE Whether to redirect the command output to a null device or not !! Defaults to .TRUE. . !! REDIRECT Filename to redirect stdout and stderr of the command into. !! If generated it is closed before run(3f) returns. !! EXITSTAT The system exit status of the command when supported by !! the system. If not present and a non-zero status is !! generated program termination occurs. !! !!##Example !! !! Sample program: !! !! Checking the error message and counting lines: !! !! program demo_run !! use fpm_filesystem, only : run !! implicit none !! logical,parameter :: T=.true., F=.false. !! integer :: exitstat !! character(len=:),allocatable :: cmd !! cmd=' ls - ltrasd * . md ' !! call run(cmd) !! call run(cmd,exitstat=exitstat) !! call run(cmd,echo=F) !! call run(cmd,verbose=F) !! end program demo_run !! subroutine run(cmd,echo,exitstat,verbose,redirect) character(len=*), intent(in) :: cmd logical,intent(in),optional :: echo integer, intent(out),optional :: exitstat logical, intent(in), optional :: verbose character(*), intent(in), optional :: redirect integer :: cmdstat character(len=256) :: cmdmsg, iomsg logical :: echo_local, verbose_local character(:), allocatable :: redirect_str character(:), allocatable :: line integer :: stat, fh, iostat if(present(echo))then echo_local=echo else echo_local=.true. end if if(present(verbose))then verbose_local=verbose else verbose_local=.true. end if if (present(redirect)) then if(redirect /= '')then redirect_str = \">\"//redirect//\" 2>&1\" else redirect_str = \"\" endif else if(verbose_local)then ! No redirection but verbose output redirect_str = \"\" else ! No redirection and non-verbose output if (os_is_unix()) then redirect_str = \" >/dev/null 2>&1\" else redirect_str = \" >NUL 2>&1\" end if end if end if if(echo_local) print *, ' + ', cmd !//redirect_str call execute_command_line(cmd//redirect_str, exitstat=stat,cmdstat=cmdstat,cmdmsg=cmdmsg) if(cmdstat /= 0)then write(*,' ( a ) ')' < ERROR > : failed command '//cmd//redirect_str call fpm_stop(1,' * run * : '//trim(cmdmsg)) endif if (verbose_local.and.present(redirect)) then open(newunit=fh,file=redirect,status=' old ',iostat=iostat,iomsg=iomsg) if(iostat == 0)then do call getline(fh, line, iostat) if (iostat /= 0) exit write(*,' ( A ) ') trim(line) end do else write(*,' ( A ) ') trim(iomsg) endif close(fh) end if if (present(exitstat)) then exitstat = stat elseif (stat /= 0) then call fpm_stop(stat,' * run * : Command '//cmd//redirect_str//' returned a non - zero status code ') end if end subroutine run !> Delete directory using system OS remove directory commands subroutine os_delete_dir(is_unix, dir, echo) logical, intent(in) :: is_unix character(len=*), intent(in) :: dir logical, intent(in), optional :: echo if (is_unix) then call run(' rm - rf ' // dir, echo=echo,verbose=.false.) else call run(' rmdir / s / q ' // dir, echo=echo,verbose=.false.) end if end subroutine os_delete_dir !> Determine the path prefix to the local folder. Used for installation, registry etc. function get_local_prefix(os) result(prefix) !> Installation prefix character(len=:), allocatable :: prefix !> Platform identifier integer, intent(in), optional :: os !> Default installation prefix on Unix platforms character(len=*), parameter :: default_prefix_unix = \"/usr/local\" !> Default installation prefix on Windows platforms character(len=*), parameter :: default_prefix_win = \"C:\\\" character(len=:), allocatable :: home if (os_is_unix(os)) then home=get_env(' HOME ','') if (home /= '' ) then prefix = join_path(home, \".local\") else prefix = default_prefix_unix end if else home=get_env(' APPDATA ','') if (home /= '' ) then prefix = join_path(home, \"local\") else prefix = default_prefix_win end if end if end function get_local_prefix !> Returns .true. if provided path is absolute. !> !> `~` not treated as absolute. logical function is_absolute_path(path, is_unix) character(len=*), intent(in) :: path logical, optional, intent(in):: is_unix character(len=*), parameter :: letters = ' ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' logical :: is_unix_os if (present(is_unix)) then is_unix_os = is_unix else is_unix_os = os_is_unix() end if if (is_unix_os) then is_absolute_path = path(1:1) == ' / ' else if (len(path) < 2) then is_absolute_path = .false. return end if is_absolute_path = index(letters, path(1:1)) /= 0 .and. path(2:2) == ' : ' end if end function is_absolute_path !> Get the HOME directory on Unix and the %USERPROFILE% directory on Windows. subroutine get_home(home, error) character(len=:), allocatable, intent(out) :: home type(error_t), allocatable, intent(out) :: error if (os_is_unix()) then home=get_env(' HOME ','') if ( home == '' ) then call fatal_error(error, \"Couldn' t retrieve 'HOME' variable \") return end if else home=get_env('USERPROFILE','') if ( home == '' ) then call fatal_error(error, \" Couldn 't retrieve ' % USERPROFILE % ' variable\") return end if end if end subroutine get_home !> Execute command line and return output as a string. subroutine execute_and_read_output(cmd, output, error, verbose) !> Command to execute. character(len=*), intent(in) :: cmd !> Command line output. character(len=:), allocatable, intent(out) :: output !> Error to handle. type(error_t), allocatable, intent(out) :: error !> Print additional information if true. logical, intent(in), optional :: verbose integer :: exitstat, unit, stat character(len=:), allocatable :: cmdmsg, tmp_file, output_line logical :: is_verbose if (present(verbose)) then is_verbose = verbose else is_verbose = .false. end if tmp_file = get_temp_filename() call run(cmd//' > '//tmp_file, exitstat=exitstat, echo=is_verbose) if (exitstat /= 0) call fatal_error(error, ' * run * : '//\"Command failed: ' \"//cmd//\" '. Message: ' \"//trim(cmdmsg)//\" '.\") open(newunit=unit, file=tmp_file, action=' read ', status=' old ') output = '' do call getline(unit, output_line, stat) if (stat /= 0) exit output = output//output_line//' ' end do if (is_verbose) print *, output close(unit, status=' delete ') end !> Ensure a windows path is converted to an 8.3 DOS path if it contains spaces function get_dos_path(path,error) character(len=*), intent(in) :: path type(error_t), allocatable, intent(out) :: error character(len=:), allocatable :: get_dos_path character(:), allocatable :: redirect,screen_output,line integer :: stat,cmdstat,iunit,last ! Non-Windows OS if (get_os_type()/=OS_WINDOWS) then get_dos_path = path return end if ! Trim path first get_dos_path = trim(path) !> No need to convert if there are no spaces has_spaces: if (scan(get_dos_path,' ')>0) then redirect = get_temp_filename() call execute_command_line(' cmd / c for % A in ( \"'//path//'\" ) do @ echo % ~ sA > '//redirect//' 2 > & 1 ',& exitstat=stat,cmdstat=cmdstat) !> Read screen output command_OK: if (cmdstat==0 .and. stat==0) then allocate(character(len=0) :: screen_output) open(newunit=iunit,file=redirect,status=' old ',iostat=stat) if (stat == 0)then do call getline(iunit, line, stat) if (stat /= 0) exit screen_output = screen_output//line//' ' end do ! Close and delete file close(iunit,status=' delete ') else call fatal_error(error,' cannot read temporary file from successful DOS path evaluation ') return endif else command_OK call fatal_error(error,' unsuccessful Windows -> DOS path command ') return end if command_OK get_dos_path = trim(adjustl(screen_output)) endif has_spaces !> Ensure there are no trailing slashes last = len_trim(get_dos_path) if (last>1 .and. get_dos_path(last:last)==' / ' .or. get_dos_path(last:last)==' \\' ) get_dos_path = get_dos_path ( 1 : last - 1 ) end function get_dos_path end module fpm_filesystem","tags":"","loc":"sourcefile/fpm_filesystem.f90.html"},{"title":"Packaging and contributing – Fortran-lang/fpm","text":"","tags":"","loc":"page/index.html"},{"title":"Contributing Guidelines – Fortran-lang/fpm","text":"Contributing to the Fortran Package Manager Thank you for considering contributing to the Fortran Package Manager ( fpm ).\nPlease review and follow these guidelines to make the contribution process\nsimple and effective for all involved. It will help communicate that you\nrespect the time of the community developers. In return, the community will\nhelp address your problem, evaluate changes, and guide you through your pull\nrequests. By contributing to fpm , you certify that you own or are allowed to share the\ncontent of your contribution under the fpm license . Style Reporting a bug Suggesting a feature Workflow General guidelines For new contributors Style Please follow the Fortran stdlib style guide for any Fortran code that you contribute.\nThis allows us to focus on substance rather than style. Reporting a bug A bug is a demonstrable problem caused by the code in this repository.\nGood bug reports are extremely valuable to us—thank you! Before opening a bug report: Check if the issue has already been reported\n ( issues ). Check if it is still an issue or it has been fixed?\n Try to reproduce it with the latest version from the default branch. Isolate the problem and create a minimal test case. A good bug report should include all information needed to reproduce the bug.\nPlease be as detailed as possible: Which version of fpm are you using? Please be specific. What are the steps to reproduce the issue? What is the expected outcome? What happens instead? This information will help the community diagnose the issue quickly and with\nminimal back-and-forth. Suggesting a feature Before suggesting a new feature, take a moment to find out if it fits the scope\nof the project, or if it has already been discussed. It is up to you to provide\na strong argument to convince the community of the benefits of this feature.\nPlease provide as much detail and context as possible. If applicable, include a\nmocked-up snippet of what the output or behavior would look like with this\nfeature implemented. “Crazy”, out-of-the-box ideas are especially welcome.\nIt’s quite possible that we are not considering an unusually creative solution. Workflow fpm is a community project. There is no one single person making final\ndecisions. This is the workflow that we follow: Open a new issue to\n describe a bug or propose a new feature.\n Refer to the earlier sections on how to write a good bug report or feature\n request. Discuss with the community and reach majority consensus about what should be\n done about the bug or feature request.\n We define “majority” loosely as 80%.\n This means that at least 4 of 5 people engaged in the discussion should be\n able to agree on the next step.\n This allows us to have the community mostly agree while not getting stuck if\n one person disagrees.\n At this stage, the scope of the fix/feature, its behavior, and API if\n applicable should be defined.\n Only when you have community consensus on these items you should proceed to\n writing code and opening a PR. When actively working on code towards a PR, please assign yourself to the\n issue on GitHub. This is good collaborative practice to avoid duplicated effort and also\n inform others what you are currently working on. Open a new Pull Request (PR) with your contribution.\n The body of the PR should at least include a bullet-point summary of the\n changes, and a detailed description is encouraged.\n If the PR completely addresses the issue you opened in step 1, include in\n the PR description the following line: Fixes # . Request reviewers to your PR.\n For small bug fixes or documentation improvements, 1 to 2 reviewers is\n sufficient.\n For implementation of bigger features, request 3 to 4 or more reviewers.\n Ideally, request reviewers that participated in step 2. If your PR implements a feature that adds or changes the behavior of fpm ,\n your PR must also include appropriate changes to the documentation. This workflow can evolve and change over time as we learn how best to work\ntogether. If you have an idea on how to improve the workflow itself, please\nopen an issue and we’ll discuss it. General guidelines A PR should implement only one feature or bug fix. Do not commit changes to files that are irrelevant to your feature or bug fix. Smaller PRs are better than large PRs, and will lead to a shorter review and\n merge cycle Add tests for your feature or bug fix to be sure that it stays functional and useful Be open to constructive criticism and requests for improving your code. Again, please follow the Fortran stdlib style guide . For new contributors If you have never created a pull request before, welcome :tada:.\nYou can learn how from this great tutorial . Don’t know where to start?\nYou can start by looking through the list of open issues .","tags":"","loc":"page/Contributing.html"},{"title":"License – Fortran-lang/fpm","text":"MIT License Copyright (c) 2020 fpm contributors Permission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the “Software”), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","tags":"","loc":"page/License.html"},{"title":"Manifest reference – Fortran-lang/fpm","text":"301 - Moved This document now lives at https://fpm.fortran-lang.org/spec/manifest.html","tags":"","loc":"page/Manifest.html"},{"title":"Packaging with fpm – Fortran-lang/fpm","text":"Preparing your package for FPM This document describes how you need to organize your application or library for\nit to successfully build with the Fortran Package Manager ( fpm ). What kind of package can fpm build? Example package layouts Single program Single-module library Multi-module library Application and library Multi-level library Be more explicit Add some tests Adding dependencies Custom build scripts What kind of package can fpm build? You can use fpm to build: Applications (program only) Libraries (modules only) Combination of the two (programs and modules combined) Let’s look at some examples of different kinds of package layouts that you can\nuse with fpm . Example package layouts This section describes some example package layouts that you can build with fpm . You can use them to model the layout of your own package. Single program Let’s start with the simplest package imaginable—a single program without\ndependencies or modules. Here’s what the layout of the top-level directory\nlooks like: .\n├── app\n│   └── main.f90\n└── fpm.toml We have one source file ( main.f90 ) in one directory ( app ). Its contents\nare: program main print * , 'Hello, World!' end program main This program prints the usual greeting to the standard output, and nothing more. There’s another important file in the top-level directory, fpm.toml . This is fpm ’s configuration file specific to your package. It includes all the data\nthat fpm needs to build your app. In our simple case, it looks like this: name = \"hello\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" The preamble includes some metadata, such as license , author , and similar,\nthat you may have seen in other package manager configuration files. The one\noption that matters here right now is: name = \"hello\" This line specifies the name of your package, which determines the name of the\nexecutable file of your program. In this example, our program executable, once\nbuilt, will be called hello . Let’s now build this program using fpm : $ fpm build # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/hello) On the first line, we ran fpm build to compile and link the application.\nThe latter two lines are emitted by fpm , and indicate which command was\nexecuted at each build step ( gfortran ), and which files have been output\nby it: object file main.o , and executable hello . We can now run the app with fpm run : $ fpm run Hello, World! If your application needs to use a module internally, but you don’t intend\nto build it as a library to be used in other projects, you can include the\nmodule in your program source file as well.\nFor example: $ cat app / main . f90 module math_constants real , parameter :: pi = 4 * atan ( 1. ) end module math_constants program main use math_constants , only : pi print * , 'Hello, World!' print * , 'pi = ' , pi end program main Now, run this using fpm run : $ fpm run # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/hello) Hello, World! pi = 3 .14159274 Although we have named our program hello , which is the same name as the\npackage name in fpm.toml , you can name it anything you want as long as it’s\npermitted by the language. Notice that you can run fpm run , and if the package hasn’t been built yet, fpm build will run automatically for you. This is true if the source files\nhave been updated since the last build. Thus, if you want to run your\napplication, you can skip the fpm build step, and go straight to fpm run . When running your application using fpm run , the program’s exit code is\npassed by fpm back to the operating system. So, it is possible to use Fortran\nnumbered stop and error stop codes to pass termination reasons back to the terminal. Try running the following app with fpm run : program main use math_constants , only : pi real :: angle read ( * , * , iostat = ierr ) angle if ( ierr /= 0 ) then stop 2 ! Not real elseif ( angle > pi ) then stop 1 else stop 0 endif end program main and then checking that the error code matches. Note that error codes are passed to variable $? on Unix/Mac systems, and to environment variable %errorlevel% on Windows. In this last example, our source file defined a math_constants module inside\nthe same source file as the main program. Let’s see how we can define an fpm package that makes this module available as a library. Single-module library The package layout for this example looks like this: . ├── fpm . toml └── src └── math_constants . f90 In this example we’ll build a simple math constants library that exports\nthe number pi as a parameter: $ cat src / math_constants . f90 module math_constants real , parameter :: pi = 4 * atan ( 1. ) end module math_constants and our fpm.toml is the same as before. Now use fpm build to build the package: $ fpm build # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a Based on the output of fpm build , fpm first ran gfortran to emit the\nbinary object ( math_constants.o ) and module ( math_constants.mod ) files.\nThen it ran ar to create a static library archive math_constants.a . build/debug/library is thus both your include and library path, should you\nwant to compile and link an external program with this library. For modules in the top-level ( src ) directory, fpm requires that: The module has the same name as the source file. There is only one module per file. These two requirements simplify the build process for fpm . As Fortran\ncompilers emit module files ( .mod ) with the same name as the module itself\n(but not the source file, .f90 ), naming the module the same as the source file\nallows fpm to: Uniquely and exactly map a source file ( .f90 ) to its object ( .o ) and\nmodule ( .mod ) files. Avoid conflicts with modules of the same name that could appear in dependency\npackages (more on this in a bit). Since this is a library without executable programs, fpm run here does\nnothing. In this example, our library is made of only one module. However, most\nreal-world libraries are likely to use multiple modules. Let’s see how you can\npackage your multi-module library. Multi-module library In this example, we’ll use another module to define a 64-bit real kind\nparameter and make it available in math_constants to define pi with\nhigher precision. To make this exercise worthwhile, we’ll define another math\nconstant, Euler’s number. Our package layout looks like this: . ├── fpm . toml └── src ├── math_constants . f90 └── type_kinds . f90 And our source file contents are: $ cat src / math_constants . f90 module math_constants use type_kinds , only : rk real ( rk ), parameter :: pi = 4 * atan ( 1._rk ) real ( rk ), parameter :: e = exp ( 1._rk ) end module math_constants $ cat src / type_kinds . f90 module type_kinds use iso_fortran_env , only : real64 integer , parameter :: rk = real64 end module type_kinds and there are no changes to our fpm.toml relative to previous examples. Like before, notice that the module type_kinds is name exactly as the\nsource file that contains it.\nThis is important. By now you know how to build the package: $ fpm build # gfortran (for build/debug/library/type_kinds.o build/debug/library/type_kinds.mod) # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a Our build path now contains: $ ls build/debug/library/\nmath_constants.a math_constants.mod math_constants.o type_kinds.mod type_kinds.o And the static library includes all the object files: $ nm build/debug/library/math_constants.a\n\nmath_constants.o:\n\ntype_kinds.o: The takeaways from this example are that: fpm automatically scanned the src directory for any source files. It also resolved the dependency order between different modules. Application and library Let’s now combine the two previous examples into one: We’ll build the math\nconstants library and an executable program that uses it. We’ll use this\nprogram as a demo, and to verify that defining higher-precision constants from\nthe previous example actually worked. Here’s the package layout for your application + library package: . ├── app │ └── main . f90 ├── fpm . toml └── src ├── math_constants . f90 └── type_kinds . f90 Our fpm.toml remains unchanged and our executable program source file is: $ cat app / main . f90 program main use math_constants , only : e , pi print * , 'math_constants library demo' print * , 'pi = ' , pi print * , 'e = ' , e end program main Let’s go straight to running the demo program: $ fpm run # gfortran (for build/debug/library/type_kinds.o build/debug/library/type_kinds.mod) # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/math_constants) math_constants library demo pi = 3 .1415926535897931 e = 2 .7182818284590451 The fpm build + run process works as expected, and our program correctly\noutputs higher-precision constants. So far we covered how fpm builds: A single program A single-module library A multi-module library A program and a library However, all our modules so far have been organized in the top level source\ndirectory. More complex libraries may organize their modules in subdirectories.\nLet’s see how we can build this with fpm . Multi-level library In this example, we’ll define our library as a collection of modules, two of\nwhich are defined in a subdirectory: . ├── app │ └── main . f90 ├── fpm . toml └── src ├── math_constants │ ├── derived . f90 │ └── fundamental . f90 ├── math_constants . f90 └── type_kinds . f90 First, fpm.toml and src/type_kinds.f90 remain unchanged relative to the\nprevious example. The rest of the source files are: $ cat src / math_constants . f90 module math_constants use math_constants_fundamental , only : e , pi use math_constants_derived , only : half_pi , two_pi end module math_constants $ cat src / math_constants / fundamental . f90 module math_constants_fundamental use type_kinds , only : rk real ( rk ), parameter :: pi = 4 * atan ( 1._rk ) real ( rk ), parameter :: e = exp ( 1._rk ) end module math_constants_fundamental $ cat src / math_constants / derived . f90 module math_constants_derived use math_constants_fundamental , only : pi use type_kinds , only : rk real ( rk ), parameter :: two_pi = 2 * pi real ( rk ), parameter :: half_pi = pi / 2 end module math_constants_derived $ cat app / main . f90 program main use math_constants , only : e , pi , half_pi , two_pi print * , 'math_constants library demo' print * , 'pi = ' , pi print * , '2*pi = ' , two_pi print * , 'pi/2 = ' , half_pi print * , 'e = ' , e end program main Our top-level math_constants module now doesn’t define the constants, but\nimports them from the two modules in the subdirectory. Constants e and pi we define in the math_constants_fundamental module, and two_pi and half_pi in the math_constants_derived module. From the main program, we access all\nthe constants from the top-level module math_constants . Let’s build and run this package: $ fpm run # gfortran (for build/debug/library/type_kinds.o build/debug/library/type_kinds.mod) # gfortran (for build/debug/library/math_constants_fundamental.o build/debug/library/math_constants_fundamental.mod) # gfortran (for build/debug/library/math_constants_derived.o build/debug/library/math_constants_derived.mod) # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/math_constants) math_constants library demo pi = 3 .1415926535897931 2 *pi = 6 .2831853071795862 pi/2 = 1 .5707963267948966 e = 2 .7182818284590451 Again, fpm built and run the package as expected. Recall from an earlier example that fpm required the modules in the top-level src directory to be named the same as their source file. This is why src/math_constants.f90 defines module math_constants . For modules defined in subdirectories, there’s an additional requirement: module\nname must contain the path components of the directory that its source file is\nin. In our case, src/math_constants/fundamental.f90 defines the math_constants_fundamental module. Likewise, src/math_constants/derived.f90 defines the math_constants_derived module. This rule applies generally to any number of nested directories and modules.\nFor example, src/a/b/c/d.f90 must define a module called a_b_c_d . Takeaways from this example are that: You can place your module source files in any levels of subdirectories inside src . The module name must include the path components and the source file name–for example, src/a/b/c/d.f90 must define a module called a_b_c_d . Be more explicit So far we’ve let fpm use its defaults to determine the layout of our package.\nIt determined where our library sources would live, what the name of the\nexecutable will be, and some other things. But we can be more explicit about it,\nand make some changes to those things. Let’s look at what the fpm.toml file from our last example would look like if\nwe specified everything. name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" You can see that by making these explicit in the fpm.toml we are able to\nchange many of the settings that fpm used by default. We can change the\nfolders where our sources are stored, we can change the name of our executable,\nand we can change the name of the file our program is defined in. Add some tests fpm also provides support for unit testing. By default, fpm looks for a\nprogram in test/main.f90 which it will compile and execute with the command fpm test . The tests are treated pretty much exactly like the executables.\nLet’s define one explicitly in our fpm.toml file. We’ll make sure that our\ndefinition of pi satisfies the property sin(pi) == 0.0 . Here’s the fpm.toml file: name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" [[ test ]] name = \"runTests\" source-dir = \"test\" main = \"main.f90\" where the contents of the main.f90 file are program main use math_constants , only : pi print * , \"sin(pi) = \" , sin ( pi ) end program main With this setup, we can run our tests. $ fpm test # gfortran (for build/debug/library/type_kinds.o build/debug/library/type_kinds.mod) # gfortran (for build/debug/library/math_constants_fundamental.o build/debug/library/math_constants_fundamental.mod) # gfortran (for build/debug/library/math_constants_derived.o build/debug/library/math_constants_derived.mod) # gfortran (for build/debug/library/math_constants.o build/debug/library/math_constants.mod) # ar (for build/debug/library/math_constants.a) ar: creating build/debug/library/math_constants.a # gfortran (for build/debug/app/main.o) # gfortran (for build/debug/app/math_constants) # gfortran (for build/debug/test/main.o) # gfortran (for build/debug/test/runTests) sin ( pi ) = 1 .2246467991473532E-016 Adding dependencies Inevitably, you’ll want to be able to include other libraries in your project.\nfpm makes this incredibly simple, by taking care of fetching and compiling your\ndependencies for you. You just tell it what your dependencies are, and where to\nfind them. Let’s add a dependency to our library. Now our fpm.toml file looks\nlike this: name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [dependencies] helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" [[ test ]] name = \"runTests\" source-dir = \"test\" main = \"main.f90\" Now you can use any modules from this library anywhere in your code. Just like\nthis: program main use helloff , only : create_greeting use math_constants , only : e , pi , half_pi , two_pi print * , 'math_constants library demo' print * , 'pi = ' , pi print * , '2*pi = ' , two_pi print * , 'pi/2 = ' , half_pi print * , 'e = ' , e print * , create_greeting ( \"fpm\" ) end program main And now, fpm run will output the following: math_constants library demo pi = 3.1415926535897931 2 * pi = 6.2831853071795862 pi / 2 = 1.5707963267948966 e = 2.7182818284590451 Hello , fpm ! Additionally, any users of your library will now automatically depend on your\ndependencies too. So if you don’t need that dependency for the library, like in\nthe above example, then you can specify it for the specific executable like\nbelow. Then fpm will still fetch and compile it when building your executable,\nbut users of your library won’t have to. name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" [executable.dependencies] helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } [[ test ]] name = \"runTests\" source-dir = \"test\" main = \"main.f90\" You can also specify dependencies for your tests in a similar way, with [test.dependencies] instead of [executable.dependencies] . There’s also\nanother option for test dependencies. The below example makes the dependencies\navailable for all the tests, but again your users won’t depend on these. name = \"math_constants\" version = \"0.1.0\" license = \"MIT\" author = \"Jane Programmer\" maintainer = \"jane@example.com\" copyright = \"2020 Jane Programmer\" [library] source-dir = \"src\" [dev-dependencies] helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\" } [[ executable ]] name = \"math_constants\" source-dir = \"app\" main = \"main.f90\" [[ test ]] name = \"runTests\" source-dir = \"test\" main = \"main.f90\" You can also be specific about which version of a dependency you’d like. You can\nspecify a branch to use like helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\", branch = \"master\" } ,\nor a tag like helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\", tag = \"v1.2.3\" } ,\nor even a specific commit like helloff = { git = \"https://gitlab.com/everythingfunctional/helloff.git\", rev = \"a1b2c3\" } .\nYou can even specify the path to another folder, if for example you’ve got\nanother fpm package in the same repository. Like this: helloff = { path = \"helloff\" } . Note that you should not specify paths\noutside of your repository, or things won’t work for your users. Custom build scripts If there is something special about your library that makes fpm unable to build\nit, you can provide your own build script. fpm will then simply call your build\nscript to build the library. To specify a build script to be used, put it in the library section of your fpm.toml file, like: [library] source-dir = \"src\" build-script = \"my_build_script\" fpm will set the following environment variables to specify some parameters to\nthe build script: FC – The Fortran compiler to be used. FFLAGS – The flags that should be passed to the Fortran compiler. BUILD_DIR – Where the compiled files should be placed. INCLUDE_DIRS – The folders where any dependencies can be found, space separated.\nIt is then the responsibility of the build script to generate the appropriate\ninclude flags. Additionally, script will be called with the name of the archive ( *.a file)\nthat should be produced as the command line argument. Note: If the name of the build script is Makefile or ends with .mk , then\nthe make program will be used to run it. Not the the archive file is explicitly\nspecified as the target to be built Note: All file and directory names are specified with their full canonical\npath.","tags":"","loc":"page/Packaging.html"}]} \ No newline at end of file diff --git a/type/archiver_t.html b/type/archiver_t.html index 255fc4815b..1216cb83eb 100644 --- a/type/archiver_t.html +++ b/type/archiver_t.html @@ -118,9 +118,9 @@

    Variables

    @@ -147,13 +147,13 @@

    Type-Bound Procedures

    @@ -210,7 +210,7 @@

    Components

    - + logical, public @@ -244,7 +244,7 @@

    Components

    - + logical, public @@ -272,10 +272,10 @@

    Type-Bound Procedures

    - +

    generic, public :: - dump => dump_to_toml, dump_to_file, dump_to_unit + dump => dump_to_toml, dump_to_file, dump_to_unit

    @@ -521,7 +521,7 @@

    Arguments

    - +

    procedure, public :: dump_to_toml @@ -531,11 +531,11 @@