aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fpm/src/fpm.f9052
-rw-r--r--fpm/test/fpm_test/test_module_dependencies.f90107
2 files changed, 158 insertions, 1 deletions
diff --git a/fpm/src/fpm.f90 b/fpm/src/fpm.f90
index a84bebf..1d2b0ae 100644
--- a/fpm/src/fpm.f90
+++ b/fpm/src/fpm.f90
@@ -23,10 +23,11 @@ use,intrinsic :: iso_fortran_env, only : stdin=>input_unit, &
& stdout=>output_unit, &
& stderr=>error_unit
use fpm_manifest_dependency, only: dependency_config_t
+use, intrinsic :: iso_fortran_env, only: error_unit
implicit none
private
public :: cmd_build, cmd_run
-public :: build_model
+public :: build_model, check_modules_for_duplicates
contains
@@ -42,6 +43,8 @@ subroutine build_model(model, settings, package, error)
integer :: i, j
type(package_config_t) :: dependency
character(len=:), allocatable :: manifest, lib_dir
+
+ logical :: duplicates_found = .false.
type(string_t) :: include_dir
model%package_name = package%name
@@ -179,8 +182,55 @@ subroutine build_model(model, settings, package, error)
write(*,*)'<INFO> INCLUDE DIRECTORIES: [', string_cat(model%include_dirs,','),']'
end if
+ ! Check for duplicate modules
+ call check_modules_for_duplicates(model, duplicates_found)
+ if (duplicates_found) then
+ error stop 'Error: One or more duplicate module names found.'
+ end if
end subroutine build_model
+! 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(error_unit, *) "Warning: Module ",model%packages(k)%sources(l)%modules_provided(m)%s," 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
subroutine cmd_build(settings)
type(fpm_build_settings), intent(in) :: settings
diff --git a/fpm/test/fpm_test/test_module_dependencies.f90 b/fpm/test/fpm_test/test_module_dependencies.f90
index 4f2aa27..fe92aab 100644
--- a/fpm/test/fpm_test/test_module_dependencies.f90
+++ b/fpm/test/fpm_test/test_module_dependencies.f90
@@ -10,6 +10,7 @@ module test_module_dependencies
FPM_UNIT_CHEADER, FPM_SCOPE_UNKNOWN, FPM_SCOPE_LIB, &
FPM_SCOPE_DEP, FPM_SCOPE_APP, FPM_SCOPE_TEST
use fpm_strings, only: string_t, operator(.in.)
+ use fpm, only: check_modules_for_duplicates
implicit none
private
@@ -39,6 +40,18 @@ contains
test_missing_program_use, should_fail=.true.), &
& new_unittest("invalid-library-use", &
test_invalid_library_use, should_fail=.true.), &
+ & new_unittest("invalid-own-module-use", &
+ test_invalid_own_module_use, should_fail=.true.), &
+ & new_unittest("package-with-no-duplicates", &
+ test_package_with_no_module_duplicates), &
+ & new_unittest("package-with-duplicates-in-same-source", &
+ test_package_module_duplicates_same_source, should_fail=.true.), &
+ & new_unittest("package-with-duplicates-in-same-source", &
+ test_package_module_duplicates_same_source, should_fail=.true.), &
+ & new_unittest("package-with-duplicates-in-one-package", &
+ test_package_module_duplicates_one_package, should_fail=.true.), &
+ & new_unittest("package-with-duplicates-in-two-packages", &
+ test_package_module_duplicates_two_packages, should_fail=.true.), &
& new_unittest("subdirectory-module-use", &
test_subdirectory_module_use), &
& new_unittest("invalid-subdirectory-module-use", &
@@ -392,6 +405,100 @@ contains
call targets_from_sources(targets,model,error)
+ !> Check program with no duplicate modules
+ subroutine test_package_with_no_module_duplicates(error)
+
+ type(error_t), allocatable, intent(out) :: error
+
+ type(fpm_model_t) :: model
+ logical :: duplicates_found
+
+ allocate(model%packages(1))
+ allocate(model%packages(1)%sources(2))
+
+ model%packages(1)%sources(1) = new_test_source(FPM_UNIT_MODULE,file_name="src/my_mod_1.f90", &
+ scope = FPM_SCOPE_LIB, provides=[string_t('my_mod_1')])
+
+ model%packages(1)%sources(2) = new_test_source(FPM_UNIT_MODULE,file_name="src/my_mod_2.f90", &
+ scope = FPM_SCOPE_LIB, provides=[string_t('my_mod_2')])
+
+ call check_modules_for_duplicates(model, duplicates_found)
+ if (duplicates_found) then
+ call test_failed(error,'Duplicate modules found')
+ return
+ end if
+ end subroutine test_package_with_no_module_duplicates
+
+ !> Check program with duplicate modules in same source file
+ subroutine test_package_module_duplicates_same_source(error)
+
+ type(error_t), allocatable, intent(out) :: error
+
+ type(fpm_model_t) :: model
+ logical :: duplicates_found
+
+ allocate(model%packages(1))
+ allocate(model%packages(1)%sources(1))
+
+ model%packages(1)%sources(1) = new_test_source(FPM_UNIT_MODULE,file_name="src/my_mod_1.f90", &
+ scope = FPM_SCOPE_LIB, provides=[string_t('my_mod_1'), string_t('my_mod_1')])
+
+ call check_modules_for_duplicates(model, duplicates_found)
+ if (duplicates_found) then
+ call test_failed(error,'Duplicate modules found')
+ return
+ end if
+ end subroutine test_package_module_duplicates_same_source
+
+ !> Check program with duplicate modules in two different source files in one package
+ subroutine test_package_module_duplicates_one_package(error)
+
+ type(error_t), allocatable, intent(out) :: error
+
+ type(fpm_model_t) :: model
+ logical :: duplicates_found
+
+ allocate(model%packages(1))
+ allocate(model%packages(1)%sources(2))
+
+ model%packages(1)%sources(1) = new_test_source(FPM_UNIT_MODULE,file_name="src/my_mod_1_a.f90", &
+ scope = FPM_SCOPE_LIB, provides=[string_t('my_mod_1')])
+
+ model%packages(1)%sources(2) = new_test_source(FPM_UNIT_MODULE,file_name="src/my_mod_1_b.f90", &
+ scope = FPM_SCOPE_LIB, provides=[string_t('my_mod_1')])
+
+ call check_modules_for_duplicates(model, duplicates_found)
+ if (duplicates_found) then
+ call test_failed(error,'Duplicate modules found')
+ return
+ end if
+ end subroutine test_package_module_duplicates_one_package
+
+ !> Check program with duplicate modules in two different packages
+ subroutine test_package_module_duplicates_two_packages(error)
+
+ type(error_t), allocatable, intent(out) :: error
+
+ type(fpm_model_t) :: model
+ logical :: duplicates_found
+
+ allocate(model%packages(2))
+ allocate(model%packages(1)%sources(1))
+ allocate(model%packages(2)%sources(1))
+
+ model%packages(1)%sources(1) = new_test_source(FPM_UNIT_MODULE,file_name="src/subdir1/my_mod_1.f90", &
+ scope = FPM_SCOPE_LIB, provides=[string_t('my_mod_1')])
+
+ model%packages(2)%sources(1) = new_test_source(FPM_UNIT_MODULE,file_name="src/subdir2/my_mod_1.f90", &
+ scope = FPM_SCOPE_LIB, provides=[string_t('my_mod_1')])
+
+ call check_modules_for_duplicates(model, duplicates_found)
+ if (duplicates_found) then
+ call test_failed(error,'Duplicate modules found')
+ return
+ end if
+ end subroutine test_package_module_duplicates_two_packages
+
end subroutine test_subdirectory_module_use
!> Check program using a non-library module in a differente sub-directory