Skip to content

Commit fe4b128

Browse files
perazzmilancurcic
andauthored
Document module naming conventions (#90)
Co-authored-by: Milan Curcic <[email protected]>
1 parent d2b8ce0 commit fe4b128

File tree

4 files changed

+219
-2
lines changed

4 files changed

+219
-2
lines changed

.github/workflows/sphinx.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
CNAME: ${{ secrets.CNAME }}
4747

4848
- uses: JamesIves/[email protected]
49-
if: ${{ github.event_name == 'push' && steps.deploy-on-push.outputs.result != 0 }}
49+
if: ${{ github.event_name == 'push' }} #&& steps.deploy-on-push.outputs.result != 0 }}
5050
with:
5151
branch: gh-pages
5252
folder: _build/html

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[![test](https://github.com/fortran-lang/fpm-docs/actions/workflows/build.yaml/badge.svg)](https://github.com/fortran-lang/fpm-docs/actions/workflows/build.yaml)
55

66
Repository for building the documentation pages for the Fortran package manager (fpm).
7-
7+
88

99
## Getting started
1010

pages/spec/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ The generated API documentation of the fpm internals can be found [here](https:/
1212

1313
:::{toctree}
1414
manifest
15+
naming
1516
API documentation <https://fortran-lang.github.io/fpm>
1617
:::

pages/spec/naming.md

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# Module name requirements
2+
3+
:::{note}
4+
Module naming requirements only apply to packages which are uploaded to a fpm registry; by default, no naming rules are enforced for local fpm projects.
5+
:::
6+
7+
:::{note}
8+
TL;DR Always prefix all your module names with a standardized package prefix.
9+
- A default prefix (package name + double underscore: `my_package__*`) is always reserved by the registry
10+
- A custom prefix (no-symbols + single underscore: `mypkg_*`) can be specified, but it is subject to not being reserved in the registry yet.
11+
- Set default (`module-naming=true`) or custom (`module-naming="mypfx"`) prefix in `fpm.toml` `[build]`.
12+
:::
13+
14+
The Fortran language does not support namespaces. This means that all public names (modules, but also global subroutines and functions) must be unique in the build space.
15+
Any build that contains duplicate names will fail because it is impossible to resolve a name to a unique object.
16+
For this reason, fpm by default requires all packages to comply with simple naming conventions that apply to both the package name and its modules.
17+
18+
19+
## Fortran names: general rules
20+
21+
As of Fortran 2003 onward, valid Fortran names need to comply with the following rules:
22+
23+
- Up to 63 characters long;
24+
- Letters are case insensitive;
25+
- Must begin with a letter;
26+
- Only alphanumeric characters (letters, numbers) and underscores `_` are allowed.
27+
28+
*Examples of invalid Fortran names:*
29+
30+
```{code-block} fortran
31+
1_package ! Begins with #
32+
package$ ! Contains invalid symbol
33+
_package ! Does not begin with letter
34+
my package ! Contains space
35+
```
36+
37+
*Examples of valid Fortran names:*
38+
39+
```{code-block} fortran
40+
my_module ! Case insensitive: all versions valid,
41+
My_Module ! but resolving to the same object
42+
MY_MODULE
43+
MyModule
44+
mypackage
45+
package_module ! Underscores allowed
46+
my_package_123
47+
```
48+
49+
## fpm registry names: rules for packages and modules
50+
51+
To reduce the chance of name collisions, any Fortran module name in a package must begin with a unique prefix.
52+
Two options are offered.
53+
54+
### Default Module names
55+
56+
The default option is always valid for all packages, as it is uniquely bound to the package name. It features a fortrannized package name, followed by a double underscore, with these rules:
57+
58+
1. Must begin with their package name;
59+
2. The ``default separator`` `__` between the package name chunk and what follows must be used;
60+
3. Neither the module nor the package name shall contain the default separator sequence elsewhere.
61+
62+
:::{note}
63+
The default separator is a *double* underscore, single underscores are allowed anywhere except at the end of a package name.
64+
:::
65+
66+
*Valid enforced module names*
67+
68+
When the naming conventions are enforced, these are example modules in a package named `my_pkg` to illustrate the rules:
69+
70+
```{code-block} fortran
71+
72+
module my_pkg ! Global API
73+
module my_pkg__1 ! We can now number them
74+
module my_pkg__123
75+
module my_pkg__core
76+
module my_pkg__utils
77+
module my_pkg__with_very_long_name
78+
```
79+
80+
*Invalid enforced module names*
81+
82+
Considering the same package `my_pkg`, the following names will be invalid according to the naming rules:
83+
84+
```{code-block} fortran
85+
86+
module my_pkg__ ! Nothing follows the separator
87+
module my_pkg__1__2 ! Separator must be unique
88+
module my_pkg__90123456789012345678901234567890123456789012345678901234 ! 64 chars: too long
89+
module my_pkg__util$ ! non-Fortran name
90+
```
91+
92+
### Custom Module names
93+
94+
Optionally, one can specify a custom prefix for the package's modules. The custom prefix must be:
95+
96+
1. A valid Fortran name;
97+
2. Alphanumeric only characters (no spaces, symbols, dashes, underscores allowed).
98+
99+
Different from the default option, a custom prefix needs to be validated by the registry, which keeps a
100+
list of unique custom prefixes to prevent name collisions.
101+
102+
Module names with the custom prefix are followed by a ``single underscore`` `_`, which makes this option more flexible and backward compatible with existing packages.
103+
When a custom module prefix is specified, the default one is still available. Considering for example a package named `date-time`, with chosen prefix `dt`, the following are all valid module names:
104+
105+
```{code-block} fortran
106+
107+
module date_time ! Same as package name
108+
module dt ! Same as custom prefix
109+
module date_time__utils ! use standard naming -> double underscore
110+
module dt_utils ! custom prefix -> single underscore
111+
module dt_123 ! custom prefix
112+
module dt_1
113+
module dt__1 ! also valid
114+
```
115+
116+
### Package names
117+
118+
All packages in FPM registries must have unique names, hence they must abide to the following rules
119+
120+
1. All package names shall be valid Fortran names;
121+
2. Dash characters (`-`) are also allowed, and are treated by fpm as underscores;
122+
3. Package names may contain uppercase and lowercase characters, but their unique identification is made case insensitive;
123+
4. No duplicate package names are allowed within the same namespace.
124+
125+
*Examples of valid package names:*
126+
127+
```{code-block} fortran
128+
my_package ! 1 underscore allowed
129+
My_Package ! same as the former
130+
mypackage123 ! Numbers OK
131+
my-package ! Will be read by fpm as "my_package"
132+
```
133+
134+
*Examples of invalid package names:*
135+
136+
```fortran
137+
my__package ! Contains package__module separator
138+
package__ ! Contains separator
139+
package_ ! Ends with underscore
140+
my pac$age ! Spaces and all symbols besides `_` not allowed
141+
_my_package ! Does not begin with letter
142+
123package ! Does not begin with letter
143+
```
144+
145+
## Manifest Settings
146+
147+
:::{note}
148+
Key facts:
149+
- FPM does not apply naming requirements by default. If you want them, enable them in `fpm.toml`
150+
- FPM registries mandatorily require them. Ensure `fpm.toml` enables them.
151+
- Enable standard prefix with `module-naming=true`, custom prefix with `module-naming="prefixname"`.
152+
:::
153+
154+
Module naming requirements can be enabled in `fpm.toml` under the `build` section, using the boolean flag `module-naming`.
155+
By default, `module-naming = false`, so no registry name enforcing is checked during the build.
156+
157+
*Example:*
158+
159+
```{code-block} toml
160+
:emphasize-lines: 5
161+
[build]
162+
auto-executables = true
163+
auto-examples = false
164+
auto-tests = false
165+
module-naming = true # Use default naming convention
166+
external-modules = "netcdf"
167+
```
168+
169+
```{code-block} toml
170+
:emphasize-lines: 5
171+
[build]
172+
auto-executables = true
173+
auto-examples = false
174+
auto-tests = false
175+
module-naming = "tomlf" # Use custom prefix, "tomlf"
176+
external-modules = "netcdf"
177+
```
178+
179+
## Guidelines
180+
181+
:::{note}
182+
These are non-mandatory styling suggestions to improve code readability and uniformity.
183+
:::
184+
185+
It's recommended that the public API of each package is contained in a top-level module, whose name is same as the package name.
186+
For example, assuming a package ``DateTime`` deals with time and date in Fortran, one could have several modules deal with parts of it:
187+
188+
```{code-block} fortran
189+
module datetime__dates ; end module
190+
module datetime__time ; end module
191+
module datetime__julian; end module
192+
```
193+
194+
and a unique public API that's contained in the top-level module:
195+
196+
```{code-block} fortran
197+
module datetime
198+
use datetime__dates, only: [...]
199+
use datetime__time, only: [...]
200+
use datetime__julian, only: [...]
201+
implicit none(type,external)
202+
private
203+
204+
! Publish API
205+
public :: sub_1
206+
public :: fun_123
207+
208+
end module datetime
209+
```
210+
211+
## References
212+
213+
[1] Metcalf, Reid, Cohen, "[Modern Fortran Explained](https://dl.acm.org/doi/book/10.5555/2090092)", Oxford University Press.
214+
215+
[2] [Style Guide for Python Code](https://peps.python.org/pep-0008/#package-and-module-names)
216+

0 commit comments

Comments
 (0)