1
1
module fpm
2
2
use fpm_strings, only: string_t, operator (.in .), glob, join, string_cat, &
3
- lower, str_ends_with
3
+ lower, str_ends_with, is_fortran_name, str_begins_with_str, &
4
+ is_valid_module_name, len_trim
4
5
use fpm_backend, only: build_package
5
6
use fpm_command_line, only: fpm_build_settings, fpm_new_settings, &
6
7
fpm_run_settings, fpm_install_settings, fpm_test_settings, &
@@ -92,6 +93,8 @@ subroutine build_model(model, settings, package, error)
92
93
model% build_prefix = join_path(" build" , basename(model% compiler% fc))
93
94
94
95
model% include_tests = settings% build_tests
96
+ model% enforce_module_names = package% build% module_naming
97
+ model% module_prefix = package% build% module_prefix
95
98
96
99
allocate (model% packages(model% deps% ndep))
97
100
@@ -107,7 +110,7 @@ subroutine build_model(model, settings, package, error)
107
110
model% packages(i)% name = dependency% name
108
111
call package% version% to_string(version)
109
112
model% packages(i)% version = version
110
-
113
+
111
114
if (allocated (dependency% preprocess)) then
112
115
do j = 1 , size (dependency% preprocess)
113
116
if (dependency% preprocess(j)% name == " cpp" ) then
@@ -153,6 +156,11 @@ subroutine build_model(model, settings, package, error)
153
156
if (allocated (dependency% build% external_modules)) then
154
157
model% external_modules = [model% external_modules, dependency% build% external_modules]
155
158
end if
159
+
160
+ ! Copy naming conventions from this dependency's manifest
161
+ model% packages(i)% enforce_module_names = dependency% build% module_naming
162
+ model% packages(i)% module_prefix = dependency% build% module_prefix
163
+
156
164
end associate
157
165
end do
158
166
if (allocated (error)) return
@@ -233,7 +241,11 @@ subroutine build_model(model, settings, package, error)
233
241
write (* ,* )' <INFO> CXX COMPILER OPTIONS: ' , model% cxx_compile_flags
234
242
write (* ,* )' <INFO> LINKER OPTIONS: ' , model% link_flags
235
243
write (* ,* )' <INFO> INCLUDE DIRECTORIES: [' , string_cat(model% include_dirs,' ,' ),' ]'
236
- end if
244
+ end if
245
+
246
+ ! Check for invalid module names
247
+ call check_module_names(model, error)
248
+ if (allocated (error)) return
237
249
238
250
! Check for duplicate modules
239
251
call check_modules_for_duplicates(model, duplicates_found)
@@ -286,6 +298,99 @@ subroutine check_modules_for_duplicates(model, duplicates_found)
286
298
end do
287
299
end subroutine check_modules_for_duplicates
288
300
301
+ ! Check names of all modules in this package and its dependencies
302
+ subroutine check_module_names (model , error )
303
+ type (fpm_model_t), intent (in ) :: model
304
+ type (error_t), allocatable , intent (out ) :: error
305
+ integer :: i,j,k,l,m
306
+ logical :: valid,errors_found,enforce_this_file
307
+ type (string_t) :: package_name,module_name,package_prefix
308
+
309
+ errors_found = .false.
310
+
311
+ ! Loop through modules provided by each source file of every package
312
+ ! Add it to the array if it is not already there
313
+ ! Otherwise print out warning about duplicates
314
+ do k= 1 ,size (model% packages)
315
+
316
+ package_name = string_t(model% packages(k)% name)
317
+
318
+ ! Custom prefix is taken from each dependency's manifest
319
+ if (model% packages(k)% enforce_module_names) then
320
+ package_prefix = model% packages(k)% module_prefix
321
+ else
322
+ package_prefix = string_t(" " )
323
+ end if
324
+
325
+ ! Warn the user if some of the dependencies have loose naming
326
+ if (model% enforce_module_names .and. .not. model% packages(k)% enforce_module_names) then
327
+ write (stderr, * ) " Warning: Dependency " ,package_name% s // &
328
+ " does not enforce module naming, but project does. "
329
+ end if
330
+
331
+ do l= 1 ,size (model% packages(k)% sources)
332
+
333
+ ! Module naming is not enforced in test modules
334
+ enforce_this_file = model% enforce_module_names .and. &
335
+ model% packages(k)% sources(l)% unit_scope/= FPM_SCOPE_TEST
336
+
337
+ if (allocated (model% packages(k)% sources(l)% modules_provided)) then
338
+
339
+ do m= 1 ,size (model% packages(k)% sources(l)% modules_provided)
340
+
341
+ module_name = model% packages(k)% sources(l)% modules_provided(m)
342
+
343
+ valid = is_valid_module_name(module_name, &
344
+ package_name, &
345
+ package_prefix, &
346
+ enforce_this_file)
347
+
348
+ if (.not. valid) then
349
+
350
+ if (enforce_this_file) then
351
+
352
+ if (len_trim (package_prefix)>0 ) then
353
+
354
+ write (stderr, * ) " ERROR: Module " ,module_name% s, &
355
+ " in " ,model% packages(k)% sources(l)% file_name, &
356
+ " does not match its package name (" // package_name% s// &
357
+ " ) or custom prefix (" // package_prefix% s// " )."
358
+ else
359
+
360
+ write (stderr, * ) " ERROR: Module " ,module_name% s, &
361
+ " in " ,model% packages(k)% sources(l)% file_name, &
362
+ " does not match its package name (" // package_name% s// " )."
363
+
364
+ endif
365
+
366
+ else
367
+
368
+ write (stderr, * ) " ERROR: Module " ,module_name% s, &
369
+ " in " ,model% packages(k)% sources(l)% file_name, &
370
+ " has an invalid Fortran name. "
371
+
372
+ end if
373
+
374
+ errors_found = .true.
375
+
376
+ end if
377
+ end do
378
+ end if
379
+ end do
380
+ end do
381
+
382
+ if (errors_found) then
383
+
384
+ if (model% enforce_module_names) &
385
+ write (stderr, * ) " Hint: Try disabling module naming in the manifest: [build] module-naming=false . "
386
+
387
+ call fatal_error(error," The package contains invalid module names. " // &
388
+ " Naming conventions " // merge (' are' ,' not' ,model% enforce_module_names)// &
389
+ " being requested." )
390
+ end if
391
+
392
+ end subroutine check_module_names
393
+
289
394
subroutine cmd_build (settings )
290
395
type (fpm_build_settings), intent (in ) :: settings
291
396
type (package_config_t) :: package
0 commit comments