aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fpm/src/fpm_targets.f9093
1 files changed, 57 insertions, 36 deletions
diff --git a/fpm/src/fpm_targets.f90 b/fpm/src/fpm_targets.f90
index 03996f7..f9bbcda 100644
--- a/fpm/src/fpm_targets.f90
+++ b/fpm/src/fpm_targets.f90
@@ -259,12 +259,14 @@ function find_module_dependency(targets,module_name,include_dir) result(target_p
end function find_module_dependency
-!> For link targets, enumerate any dependency objects required for linking
+!> For libraries and executables, build a list of objects required for linking
+!>
+!> stored in `target%link_objects`
+!>
subroutine resolve_target_linking(targets)
type(build_target_ptr), intent(inout), target :: targets(:)
- integer :: i,j,k
- type(string_t) :: link_object
+ integer :: i
do i=1,size(targets)
@@ -272,47 +274,66 @@ subroutine resolve_target_linking(targets)
allocate(target%link_objects(0))
- do j=1,size(target%dependencies)
-
- if (target%target_type == FPM_TARGET_ARCHIVE ) then
-
- ! Construct object list for archive
- link_object%s = target%dependencies(j)%ptr%output_file
- target%link_objects = [target%link_objects, link_object]
-
- else if (target%target_type == FPM_TARGET_EXECUTABLE .and. &
- target%dependencies(j)%ptr%target_type == FPM_TARGET_OBJECT) then
-
- associate(exe_obj => target%dependencies(j)%ptr)
-
- ! Construct object list for executable
- link_object%s = exe_obj%output_file
- target%link_objects = [target%link_objects, link_object]
-
- ! Include non-library object dependencies
- do k=1,size(exe_obj%dependencies)
-
- if (allocated(exe_obj%dependencies(k)%ptr%source)) then
- if (exe_obj%dependencies(k)%ptr%source%unit_scope == &
- exe_obj%source%unit_scope) then
+ if (target%target_type == FPM_TARGET_ARCHIVE) then
- link_object%s = exe_obj%dependencies(k)%ptr%output_file
- target%link_objects = [target%link_objects, link_object]
+ call get_link_objects(target%link_objects,target,is_exe=.false.)
- end if
- end if
-
- end do
+ else if (target%target_type == FPM_TARGET_EXECUTABLE) then
- end associate
-
- end if
+ call get_link_objects(target%link_objects,target,is_exe=.true.)
+
+ end if
- end do
end associate
end do
+contains
+
+ !> Wrapper to build link object list
+ !>
+ !> For libraries: just list dependency objects of lib target
+ !>
+ !> For executables: need to recursively discover non-library
+ !> dependency objects. (i.e. modules in same dir as program)
+ !>
+ recursive subroutine get_link_objects(link_objects,target,is_exe)
+ type(string_t), intent(inout), allocatable :: link_objects(:)
+ type(build_target_t), intent(in) :: target
+ logical, intent(in) :: is_exe
+
+ integer :: i
+ type(string_t) :: temp_str
+
+ if (.not.allocated(target%dependencies)) return
+
+ do i=1,size(target%dependencies)
+
+ associate(dep => target%dependencies(i)%ptr)
+
+ if (.not.allocated(dep%source)) cycle
+
+ ! Skip library dependencies for executable targets
+ ! since the library archive will always be linked
+ if (is_exe.and.(dep%source%unit_scope == FPM_SCOPE_LIB)) cycle
+
+ ! Skip if dependency object already listed
+ if (dep%output_file .in. link_objects) cycle
+
+ ! Add dependency object file to link object list
+ temp_str%s = dep%output_file
+ link_objects = [link_objects, temp_str]
+
+ ! For executable objects, also need to include non-library
+ ! dependencies from dependencies (recurse)
+ if (is_exe) call get_link_objects(link_objects,dep,is_exe=.true.)
+
+ end associate
+
+ end do
+
+ end subroutine get_link_objects
+
end subroutine resolve_target_linking