Skip to content

Commit 3a698ba

Browse files
authored
Merge pull request #180 from LKedward/recursive_discovery
Recursive source discovery
2 parents e79b47e + dd02f5d commit 3a698ba

File tree

6 files changed

+103
-12
lines changed

6 files changed

+103
-12
lines changed

fpm/src/fpm_backend.f90

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module fpm_backend
22

33
! Implements the native fpm build backend
44

5-
use fpm_environment, only: run
5+
use fpm_environment, only: run, get_os_type, OS_WINDOWS
66
use fpm_filesystem, only: basename, join_path, exists, mkdir
77
use fpm_model, only: fpm_model_t, srcfile_t, FPM_UNIT_MODULE, &
88
FPM_UNIT_SUBMODULE, FPM_UNIT_SUBPROGRAM, &
@@ -109,8 +109,7 @@ recursive subroutine build_source(model,source_file,linking)
109109

110110
end do
111111

112-
object_file = join_path(model%output_directory, model%package_name, &
113-
basename(source_file%file_name,suffix=.false.)//'.o')
112+
object_file = get_object_name(model,source_file%file_name)
114113

115114
call run("gfortran -c " // source_file%file_name // model%fortran_compile_flags &
116115
// " -o " // object_file)
@@ -120,4 +119,41 @@ recursive subroutine build_source(model,source_file,linking)
120119

121120
end subroutine build_source
122121

122+
123+
function get_object_name(model,source_file_name) result(object_file)
124+
! Generate object target path from source name and model params
125+
!
126+
! src/test.f90 -> <output-dir>/<package-name>/test.o
127+
! src/subdir/test.f90 -> <output-dir>/<package-name>/subdir_test.o
128+
!
129+
type(fpm_model_t), intent(in) :: model
130+
character(*), intent(in) :: source_file_name
131+
character(:), allocatable :: object_file
132+
133+
integer :: i
134+
character(1) :: filesep
135+
136+
select case(get_os_type())
137+
case (OS_WINDOWS)
138+
filesep = '\'
139+
case default
140+
filesep = '/'
141+
end select
142+
143+
! Exclude first directory level from path
144+
object_file = source_file_name(index(source_file_name,filesep)+1:)
145+
146+
! Convert remaining directory separators to underscores
147+
i = index(object_file,filesep)
148+
do while(i > 0)
149+
object_file(i:i) = '_'
150+
i = index(object_file,filesep)
151+
end do
152+
153+
! Construct full target path
154+
object_file = join_path(model%output_directory, model%package_name, &
155+
object_file//'.o')
156+
157+
end function get_object_name
158+
123159
end module fpm_backend

fpm/src/fpm_filesystem.f90

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,25 @@ function basename(path,suffix) result (base)
4040
end function basename
4141

4242

43+
logical function is_dir(dir)
44+
character(*), intent(in) :: dir
45+
integer :: stat
46+
47+
select case (get_os_type())
48+
49+
case (OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_CYGWIN, OS_SOLARIS, OS_FREEBSD)
50+
call execute_command_line("test -d " // dir , exitstat=stat)
51+
52+
case (OS_WINDOWS)
53+
call execute_command_line('cmd /c "if not exist ' // windows_path(dir) // '\ exit /B 1"', exitstat=stat)
54+
55+
end select
56+
57+
is_dir = (stat == 0)
58+
59+
end function is_dir
60+
61+
4362
function join_path(a1,a2,a3,a4,a5) result(path)
4463
! Construct path by joining strings with os file separator
4564
!
@@ -130,11 +149,15 @@ subroutine mkdir(dir)
130149
end subroutine mkdir
131150

132151

133-
subroutine list_files(dir, files)
134-
character(len=*), intent(in) :: dir
152+
recursive subroutine list_files(dir, files, recurse)
153+
character(len=*), intent(in) :: dir
135154
type(string_t), allocatable, intent(out) :: files(:)
136-
character(len=:), allocatable :: temp_file
137-
integer :: stat, fh
155+
logical, intent(in), optional :: recurse
156+
157+
integer :: stat, fh, i
158+
character(:), allocatable :: temp_file
159+
type(string_t), allocatable :: dir_files(:)
160+
type(string_t), allocatable :: sub_dir_files(:)
138161

139162
! Using `inquire` / exists on directories works with gfortran, but not ifort
140163
if (.not. exists(dir)) then
@@ -160,7 +183,31 @@ subroutine list_files(dir, files)
160183

161184
open (newunit=fh, file=temp_file, status='old')
162185
files = read_lines(fh)
163-
close (fh, status='delete')
186+
close(fh,status="delete")
187+
188+
do i=1,size(files)
189+
files(i)%s = join_path(dir,files(i)%s)
190+
end do
191+
192+
if (present(recurse)) then
193+
if (recurse) then
194+
195+
allocate(sub_dir_files(0))
196+
197+
do i=1,size(files)
198+
if (is_dir(files(i)%s)) then
199+
200+
call list_files(files(i)%s, dir_files, recurse=.true.)
201+
sub_dir_files = [sub_dir_files, dir_files]
202+
203+
end if
204+
end do
205+
206+
files = [files, sub_dir_files]
207+
208+
end if
209+
end if
210+
164211
end subroutine list_files
165212

166213

fpm/src/fpm_sources.f90

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ subroutine add_sources_from_dir(sources,directory,with_executables,error)
3737
type(srcfile_t), allocatable :: dir_sources(:)
3838

3939
! Scan directory for sources
40-
call list_files(directory, file_names)
41-
file_names = [(string_t(directory//'/'//file_names(j)%s),j=1,size(file_names))]
40+
call list_files(directory, file_names,recurse=.true.)
4241

4342
is_source = [(str_ends_with(lower(file_names(i)%s), ".f90") .or. &
4443
str_ends_with(lower(file_names(i)%s), ".c") .or. &

test/example_packages/hello_complex/source/farewell_m.f90

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module farewell_m
2+
use subdir_constants, only: FAREWELL_STR
23
implicit none
34
private
45

@@ -8,6 +9,6 @@ function make_farewell(name) result(greeting)
89
character(len=*), intent(in) :: name
910
character(len=:), allocatable :: greeting
1011

11-
greeting = "Goodbye, " // name // "!"
12+
greeting = FAREWELL_STR // name // "!"
1213
end function make_farewell
1314
end module farewell_m

test/example_packages/hello_complex/source/greet_m.f90

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module greet_m
2+
use subdir_constants, only: GREET_STR
23
implicit none
34
private
45

@@ -8,6 +9,6 @@ function make_greeting(name) result(greeting)
89
character(len=*), intent(in) :: name
910
character(len=:), allocatable :: greeting
1011

11-
greeting = "Hello, " // name // "!"
12+
greeting = GREET_STR // name // "!"
1213
end function make_greeting
1314
end module greet_m
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module subdir_constants
2+
implicit none
3+
4+
character(*), parameter :: GREET_STR = 'Hello, '
5+
character(*), parameter :: FAREWELL_STR = 'Goodbye, '
6+
7+
end module subdir_constants

0 commit comments

Comments
 (0)