模块名称要求

请注意

模块命名要求仅适用于上传到 fpm 注册表的包;默认情况下,对于本地 fpm 项目,未实施任何命名规则。

请注意

小提示:始终使用标准化包前缀作为所有模块名称的前缀。

  • 注册表始终保留一个默认前缀(包名称 + 双下划线:my_package__*

  • 可以指定自定义前缀(无符号 + 单下划线:mypkg_*),但需遵守该前缀在注册表中尚未保留的规定。

  • fpm.toml[build] 设置默认前缀(module-naming=true)或自定义前缀(module-naming="mypfx")。

Fortran 语言不支持命名空间。这意味着在构建空间中所有的公共名称(模块,以及全局子例程和函数)必须是唯一的。任何包含重复名称的构建都将失败,因为不可能将名称解析为唯一对象。因此,fpm 默认要求所有包遵循适用于包名称及其模块的简单命名约定。

Fortran 名称:通用规则

从 Fortran 2003 起,有效的 Fortran 名称需要遵守以下规则

  • 最多 63 个字符;

  • 字母不区分大小写;

  • 必须以字母开头;

  • 只允许字母数字字符(字母、数字)和下划线 _

无效 Fortran 名称的示例

  1_package         ! Begins with #
  package$          ! Contains invalid symbol
  _package          ! Does not begin with letter
  my package        ! Contains space

有效 Fortran 名称的示例

  my_module         ! Case insensitive: all versions valid,
  My_Module         ! but resolving to the same object
  MY_MODULE
  MyModule
  mypackage
  package_module    ! Underscores allowed
  my_package_123

fpm 注册表名称:包和模块的规则

为了减少名称冲突的几率,包中的任何 Fortran 模块名称都必须以一个唯一前缀开头。提供了两个选项。

默认模块名称

默认选项始终对所有包有效,因为它与包名称唯一绑定。它具有一个 Fortran 形式的包名称,后面跟着一个双下划线,并遵守以下规则

  1. 必须以包名称开头;

  2. 包名称部分和后面部分之间的 default separator __ 必须使用;

  3. 模块和包名称不得在其他地方包含默认分隔符序列。

请注意

默认分隔符是一个下划线,单下划线除包名称末尾外,在任何地方都允许使用。

有效的强制模块名称

当强制执行命名约定时,以下是名为 my_pkg 的包中的示例模块,以说明这些规则

   module my_pkg        ! Global API
   module my_pkg__1     ! We can now number them
   module my_pkg__123
   module my_pkg__core
   module my_pkg__utils
   module my_pkg__with_very_long_name

无效的强制模块名称

考虑同一个包 my_pkg,以下名称将根据命名规则无效

   module my_pkg__      ! Nothing follows the separator
   module my_pkg__1__2  ! Separator must be unique
   module my_pkg__90123456789012345678901234567890123456789012345678901234 ! 64 chars: too long
   module my_pkg__util$ ! non-Fortran name

自定义模块名称

或者,可以为包的模块指定自定义前缀。自定义前缀必须是

  1. 有效的 Fortran 名称;

  2. 仅限字母数字字符(不允许空格、符号、破折号、下划线)。

与默认选项不同,自定义前缀需要由注册表验证,后者保留唯一自定义前缀列表,以防止名称冲突。

具有自定义前缀的模块名后面跟随一个 下划线 _,这使此选项更具灵活性,并向后兼容现有的包。当指定自定义模块前缀时,默认前缀仍然可用。例如考虑一个名为 date-time,选择前缀 dt 的包,以下是所有有效的模块名

   module date_time        ! Same as package name
   module dt               ! Same as custom prefix
   module date_time__utils ! use standard naming -> double underscore
   module dt_utils         ! custom prefix -> single underscore
   module dt_123           ! custom prefix
   module dt_1
   module dt__1            ! also valid

包名

FPM 注册表中的所有包必须具有唯一的名称,因此它们必须遵守以下规则

  1. 所有包名应为有效的 Fortran 名称;

  2. 连字符(-)也允许,并且 fpm 将其视为下划线;

  3. 包名可以包含大写和小写字符,但它们的唯一标识不区分大小写;

  4. 在同一名称空间内不允许有重复的包名。

有效包名的示例

   my_package     ! 1 underscore allowed
   My_Package     ! same as the former
   mypackage123   ! Numbers OK
   my-package     ! Will be read by fpm as "my_package"

无效包名的示例

  my__package       ! Contains package__module separator
  package__         ! Contains separator
  package_          ! Ends with underscore
  my pac$age        ! Spaces and all symbols besides `_` not allowed
  _my_package       ! Does not begin with letter
  123package        ! Does not begin with letter

清单设置

请注意

关键事实

  • 默认情况下,FPM 不应用命名要求。如果您需要,请在 fpm.toml 中启用它们

  • FPM 注册表强制要求它们。请确保 fpm.toml 已启用它们。

  • 使用 module-naming=true 启用标准前缀,使用 module-naming="prefixname" 启用自定义前缀。

可以在 fpm.tomlbuild 部分下使用布尔标志 module-naming来启用模块命名要求。默认情况下,module-naming = false,因此在构建期间不会检查注册表名称强制实施情况。

示例

[build]
auto-executables = true
auto-examples = false
auto-tests = false
module-naming = true          # Use default naming convention
external-modules = "netcdf"
[build]
auto-executables = true
auto-examples = false
auto-tests = false
module-naming = "tomlf"       # Use custom prefix, "tomlf"
external-modules = "netcdf"

指南

请注意

以下是一些非强制性的样式建议,以提高代码的可读性和一致性。

建议将每个包的公共 API 包含在顶层模块中,其名称与包名相同。例如,假设包 DateTime 在 Fortran 中处理时间和日期,一个人可以有几个模块来处理它的部分

   module datetime__dates ; end module
   module datetime__time  ; end module
   module datetime__julian; end module

和一个包含在顶层模块中的唯一公共 API

   module datetime
      use datetime__dates, only: [...]
      use datetime__time, only: [...]
      use datetime__julian, only: [...]
      implicit none(type,external)
      private

      ! Publish API
      public :: sub_1
      public :: fun_123

   end module datetime

参考

[1] 梅特卡夫、里德、科恩,“现代 Fortran 解释”,牛津大学出版社。

[2] Python 代码风格指南