|
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, &
|
@@ -96,6 +97,8 @@ subroutine build_model(model, settings, package, error)
|
96 | 97 | model%build_prefix = join_path("build", basename(model%compiler%fc))
|
97 | 98 |
|
98 | 99 | model%include_tests = settings%build_tests
|
| 100 | + model%enforce_module_names = package%build%module_naming |
| 101 | + model%module_prefix = package%build%module_prefix |
99 | 102 |
|
100 | 103 | allocate(model%packages(model%deps%ndep))
|
101 | 104 |
|
@@ -157,6 +160,11 @@ subroutine build_model(model, settings, package, error)
|
157 | 160 | if (allocated(dependency%build%external_modules)) then
|
158 | 161 | model%external_modules = [model%external_modules, dependency%build%external_modules]
|
159 | 162 | end if
|
| 163 | + |
| 164 | + ! Copy naming conventions from this dependency's manifest |
| 165 | + model%packages(i)%enforce_module_names = dependency%build%module_naming |
| 166 | + model%packages(i)%module_prefix = dependency%build%module_prefix |
| 167 | + |
160 | 168 | end associate
|
161 | 169 | end do
|
162 | 170 | if (allocated(error)) return
|
@@ -237,7 +245,11 @@ subroutine build_model(model, settings, package, error)
|
237 | 245 | write(*,*)'<INFO> CXX COMPILER OPTIONS: ', model%cxx_compile_flags
|
238 | 246 | write(*,*)'<INFO> LINKER OPTIONS: ', model%link_flags
|
239 | 247 | write(*,*)'<INFO> INCLUDE DIRECTORIES: [', string_cat(model%include_dirs,','),']'
|
240 |
| - end if |
| 248 | + end if |
| 249 | + |
| 250 | + ! Check for invalid module names |
| 251 | + call check_module_names(model, error) |
| 252 | + if (allocated(error)) return |
241 | 253 |
|
242 | 254 | ! Check for duplicate modules
|
243 | 255 | call check_modules_for_duplicates(model, duplicates_found)
|
@@ -290,6 +302,99 @@ subroutine check_modules_for_duplicates(model, duplicates_found)
|
290 | 302 | end do
|
291 | 303 | end subroutine check_modules_for_duplicates
|
292 | 304 |
|
| 305 | +! Check names of all modules in this package and its dependencies |
| 306 | +subroutine check_module_names(model, error) |
| 307 | + type(fpm_model_t), intent(in) :: model |
| 308 | + type(error_t), allocatable, intent(out) :: error |
| 309 | + integer :: i,j,k,l,m |
| 310 | + logical :: valid,errors_found,enforce_this_file |
| 311 | + type(string_t) :: package_name,module_name,package_prefix |
| 312 | + |
| 313 | + errors_found = .false. |
| 314 | + |
| 315 | + ! Loop through modules provided by each source file of every package |
| 316 | + ! Add it to the array if it is not already there |
| 317 | + ! Otherwise print out warning about duplicates |
| 318 | + do k=1,size(model%packages) |
| 319 | + |
| 320 | + package_name = string_t(model%packages(k)%name) |
| 321 | + |
| 322 | + ! Custom prefix is taken from each dependency's manifest |
| 323 | + if (model%packages(k)%enforce_module_names) then |
| 324 | + package_prefix = model%packages(k)%module_prefix |
| 325 | + else |
| 326 | + package_prefix = string_t("") |
| 327 | + end if |
| 328 | + |
| 329 | + ! Warn the user if some of the dependencies have loose naming |
| 330 | + if (model%enforce_module_names .and. .not.model%packages(k)%enforce_module_names) then |
| 331 | + write(stderr, *) "Warning: Dependency ",package_name%s // & |
| 332 | + " does not enforce module naming, but project does. " |
| 333 | + end if |
| 334 | + |
| 335 | + do l=1,size(model%packages(k)%sources) |
| 336 | + |
| 337 | + ! Module naming is not enforced in test modules |
| 338 | + enforce_this_file = model%enforce_module_names .and. & |
| 339 | + model%packages(k)%sources(l)%unit_scope/=FPM_SCOPE_TEST |
| 340 | + |
| 341 | + if (allocated(model%packages(k)%sources(l)%modules_provided)) then |
| 342 | + |
| 343 | + do m=1,size(model%packages(k)%sources(l)%modules_provided) |
| 344 | + |
| 345 | + module_name = model%packages(k)%sources(l)%modules_provided(m) |
| 346 | + |
| 347 | + valid = is_valid_module_name(module_name, & |
| 348 | + package_name, & |
| 349 | + package_prefix, & |
| 350 | + enforce_this_file) |
| 351 | + |
| 352 | + if (.not.valid) then |
| 353 | + |
| 354 | + if (enforce_this_file) then |
| 355 | + |
| 356 | + if (len_trim(package_prefix)>0) then |
| 357 | + |
| 358 | + write(stderr, *) "ERROR: Module ",module_name%s, & |
| 359 | + " in ",model%packages(k)%sources(l)%file_name, & |
| 360 | + " does not match its package name ("//package_name%s// & |
| 361 | + ") or custom prefix ("//package_prefix%s//")." |
| 362 | + else |
| 363 | + |
| 364 | + write(stderr, *) "ERROR: Module ",module_name%s, & |
| 365 | + " in ",model%packages(k)%sources(l)%file_name, & |
| 366 | + " does not match its package name ("//package_name%s//")." |
| 367 | + |
| 368 | + endif |
| 369 | + |
| 370 | + else |
| 371 | + |
| 372 | + write(stderr, *) "ERROR: Module ",module_name%s, & |
| 373 | + " in ",model%packages(k)%sources(l)%file_name, & |
| 374 | + " has an invalid Fortran name. " |
| 375 | + |
| 376 | + end if |
| 377 | + |
| 378 | + errors_found = .true. |
| 379 | + |
| 380 | + end if |
| 381 | + end do |
| 382 | + end if |
| 383 | + end do |
| 384 | + end do |
| 385 | + |
| 386 | + if (errors_found) then |
| 387 | + |
| 388 | + if (model%enforce_module_names) & |
| 389 | + write(stderr, *) " Hint: Try disabling module naming in the manifest: [build] module-naming=false . " |
| 390 | + |
| 391 | + call fatal_error(error,"The package contains invalid module names. "// & |
| 392 | + "Naming conventions "//merge('are','not',model%enforce_module_names)// & |
| 393 | + " being requested.") |
| 394 | + end if |
| 395 | + |
| 396 | +end subroutine check_module_names |
| 397 | + |
293 | 398 | subroutine cmd_build(settings)
|
294 | 399 | type(fpm_build_settings), intent(in) :: settings
|
295 | 400 | type(package_config_t) :: package
|
|
0 commit comments