Skip to content

Commit 5c6dcfc

Browse files
committed
serialize executable_config_t
1 parent 569f898 commit 5c6dcfc

File tree

3 files changed

+246
-6
lines changed

3 files changed

+246
-6
lines changed

src/fpm/manifest/dependency.f90

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ module fpm_manifest_dependency
3535
private
3636

3737
public :: dependency_config_t, new_dependency, new_dependencies, manifest_has_changed, &
38-
& dependency_destroy
38+
& dependency_destroy, resize
3939

4040
!> Configuration meta data for a dependency
4141
type, extends(serializable_t) :: dependency_config_t
@@ -73,6 +73,10 @@ module fpm_manifest_dependency
7373
!> Common output format for writing to the command line
7474
character(len=*), parameter :: out_fmt = '("#", *(1x, g0))'
7575

76+
interface resize
77+
module procedure resize_dependency_config
78+
end interface resize
79+
7680
contains
7781

7882
!> Construct a new dependency configuration from a TOML data structure
@@ -438,4 +442,39 @@ subroutine load_from_toml(self, table, error)
438442

439443
end subroutine load_from_toml
440444

445+
!> Reallocate a list of dependencies
446+
pure subroutine resize_dependency_config(var, n)
447+
!> Instance of the array to be resized
448+
type(dependency_config_t), allocatable, intent(inout) :: var(:)
449+
!> Dimension of the final array size
450+
integer, intent(in), optional :: n
451+
452+
type(dependency_config_t), allocatable :: tmp(:)
453+
integer :: this_size, new_size
454+
integer, parameter :: initial_size = 16
455+
456+
if (allocated(var)) then
457+
this_size = size(var, 1)
458+
call move_alloc(var, tmp)
459+
else
460+
this_size = initial_size
461+
end if
462+
463+
if (present(n)) then
464+
new_size = n
465+
else
466+
new_size = this_size + this_size/2 + 1
467+
end if
468+
469+
allocate (var(new_size))
470+
471+
if (allocated(tmp)) then
472+
this_size = min(size(tmp, 1), size(var, 1))
473+
var(:this_size) = tmp(:this_size)
474+
deallocate (tmp)
475+
end if
476+
477+
end subroutine resize_dependency_config
478+
479+
441480
end module fpm_manifest_dependency

src/fpm/manifest/executable.f90

Lines changed: 165 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@
1111
!>[executable.dependencies]
1212
!>```
1313
module fpm_manifest_executable
14-
use fpm_manifest_dependency, only : dependency_config_t, new_dependencies
15-
use fpm_error, only : error_t, syntax_error, bad_name_error
16-
use fpm_strings, only : string_t
17-
use fpm_toml, only : toml_table, toml_key, toml_stat, get_value, get_list
14+
use fpm_manifest_dependency, only : dependency_config_t, new_dependencies, resize
15+
use fpm_error, only : error_t, syntax_error, bad_name_error, fatal_error
16+
use fpm_strings, only : string_t, operator(==)
17+
use fpm_toml, only : toml_table, toml_key, toml_stat, get_value, get_list, serializable_t, add_table, &
18+
set_string, set_list
1819
implicit none
1920
private
2021

2122
public :: executable_config_t, new_executable
2223

2324

2425
!> Configuation meta data for an executable
25-
type :: executable_config_t
26+
type, extends(serializable_t) :: executable_config_t
2627

2728
!> Name of the resulting executable
2829
character(len=:), allocatable :: name
@@ -44,8 +45,15 @@ module fpm_manifest_executable
4445
!> Print information on this instance
4546
procedure :: info
4647

48+
!> Serialization interface
49+
procedure :: serializable_is_same => exe_is_same
50+
procedure :: dump_to_toml
51+
procedure :: load_from_toml
52+
4753
end type executable_config_t
4854

55+
character(*), parameter, private :: class_name = 'executable_config_t'
56+
4957

5058
contains
5159

@@ -186,4 +194,156 @@ subroutine info(self, unit, verbosity)
186194
end subroutine info
187195

188196

197+
logical function exe_is_same(this,that)
198+
class(executable_config_t), intent(in) :: this
199+
class(serializable_t), intent(in) :: that
200+
201+
integer :: ii
202+
203+
exe_is_same = .false.
204+
205+
select type (other=>that)
206+
type is (executable_config_t)
207+
if (.not.this%link==other%link) return
208+
if (.not.allocated(this%name).eqv.allocated(other%name)) return
209+
if (.not.this%name==other%name) return
210+
if (.not.allocated(this%source_dir).eqv.allocated(other%source_dir)) return
211+
if (.not.this%source_dir==other%source_dir) return
212+
if (.not.allocated(this%main).eqv.allocated(other%main)) return
213+
if (.not.this%main==other%main) return
214+
if (.not.allocated(this%dependency).eqv.allocated(other%dependency)) return
215+
if (allocated(this%dependency)) then
216+
if (.not.(size(this%dependency)==size(other%dependency))) return
217+
do ii = 1, size(this%dependency)
218+
if (.not.(this%dependency(ii)==other%dependency(ii))) return
219+
end do
220+
end if
221+
class default
222+
! Not the same type
223+
return
224+
end select
225+
226+
!> All checks passed!
227+
exe_is_same = .true.
228+
229+
end function exe_is_same
230+
231+
!> Dump install config to toml table
232+
subroutine dump_to_toml(self, table, error)
233+
234+
!> Instance of the serializable object
235+
class(executable_config_t), intent(inout) :: self
236+
237+
!> Data structure
238+
type(toml_table), intent(inout) :: table
239+
240+
!> Error handling
241+
type(error_t), allocatable, intent(out) :: error
242+
243+
!> Local variables
244+
integer :: ierr, ii
245+
type(toml_table), pointer :: ptr_deps,ptr
246+
character(27) :: unnamed
247+
248+
call set_string(table, "name", self%name, error)
249+
if (allocated(error)) return
250+
call set_string(table, "source-dir", self%source_dir, error)
251+
if (allocated(error)) return
252+
call set_string(table, "main", self%main, error)
253+
if (allocated(error)) return
254+
255+
if (allocated(self%dependency)) then
256+
257+
! Create dependency table
258+
call add_table(table, "dependencies", ptr_deps)
259+
if (.not. associated(ptr_deps)) then
260+
call fatal_error(error, class_name//" cannot create dependency table ")
261+
return
262+
end if
263+
264+
do ii = 1, size(self%dependency)
265+
associate (dep => self%dependency(ii))
266+
267+
!> Because dependencies are named, fallback if this has no name
268+
!> So, serialization will work regardless of size(self%dep) == self%ndep
269+
if (len_trim(dep%name)==0) then
270+
write(unnamed,1) ii
271+
call add_table(ptr_deps, trim(unnamed), ptr)
272+
else
273+
call add_table(ptr_deps, dep%name, ptr)
274+
end if
275+
if (.not. associated(ptr)) then
276+
call fatal_error(error, class_name//" cannot create entry for dependency "//dep%name)
277+
return
278+
end if
279+
call dep%dump_to_toml(ptr, error)
280+
if (allocated(error)) return
281+
end associate
282+
end do
283+
284+
endif
285+
286+
call set_list(table, "link", self%link, error)
287+
if (allocated(error)) return
288+
289+
1 format('UNNAMED_DEPENDENCY_',i0)
290+
291+
end subroutine dump_to_toml
292+
293+
!> Read install config from toml table (no checks made at this stage)
294+
subroutine load_from_toml(self, table, error)
295+
296+
!> Instance of the serializable object
297+
class(executable_config_t), intent(inout) :: self
298+
299+
!> Data structure
300+
type(toml_table), intent(inout) :: table
301+
302+
!> Error handling
303+
type(error_t), allocatable, intent(out) :: error
304+
305+
!> Local variables
306+
type(toml_key), allocatable :: keys(:),dep_keys(:)
307+
type(toml_table), pointer :: ptr_deps,ptr
308+
integer :: ii, jj, ierr
309+
310+
call table%get_keys(keys)
311+
312+
call get_value(table, "name", self%name)
313+
if (allocated(error)) return
314+
call get_value(table, "source-dir", self%source_dir)
315+
if (allocated(error)) return
316+
call get_value(table, "main", self%main)
317+
if (allocated(error)) return
318+
call get_list(table, "link", self%link, error)
319+
320+
find_deps_table: do ii = 1, size(keys)
321+
if (keys(ii)%key=="dependencies") then
322+
323+
call get_value(table, keys(ii), ptr_deps)
324+
if (.not.associated(ptr_deps)) then
325+
call fatal_error(error,class_name//': error retrieving dependency table from TOML table')
326+
return
327+
end if
328+
329+
!> Read all dependencies
330+
call ptr_deps%get_keys(dep_keys)
331+
call resize(self%dependency, size(dep_keys))
332+
333+
do jj = 1, size(dep_keys)
334+
335+
call get_value(ptr_deps, dep_keys(jj), ptr)
336+
call self%dependency(jj)%load_from_toml(ptr, error)
337+
if (allocated(error)) return
338+
339+
end do
340+
341+
exit find_deps_table
342+
343+
endif
344+
end do find_deps_table
345+
346+
end subroutine load_from_toml
347+
348+
189349
end module fpm_manifest_executable

test/fpm_test/test_toml.f90

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module test_toml
1010
use fpm_manifest_install
1111
use fpm_manifest_fortran
1212
use fpm_manifest_library
13+
use fpm_manifest_executable
1314
use fpm_versioning, only: new_version
1415
use fpm_strings, only: string_t, operator(==), split
1516
use fpm_model, only: fortran_features_t, package_t, FPM_SCOPE_LIB, FPM_UNIT_MODULE, fpm_model_t, &
@@ -1212,4 +1213,44 @@ subroutine library_config_roundtrip(error)
12121213

12131214
end subroutine library_config_roundtrip
12141215

1216+
1217+
subroutine executable_config_roundtrip(error)
1218+
1219+
!> Error handling
1220+
type(error_t), allocatable, intent(out) :: error
1221+
1222+
type(executable_config_t) :: exe
1223+
type(dependency_config_t) :: dep
1224+
1225+
exe%name = "my_executable"
1226+
exe%source_dir = 'app'
1227+
1228+
call exe%test_serialization('executable_config: 1',error)
1229+
if (allocated(error)) return
1230+
1231+
exe%main = 'main_program.F90'
1232+
1233+
call exe%test_serialization('executable_config: 2',error)
1234+
if (allocated(error)) return
1235+
1236+
exe%link = [string_t('netcdf'),string_t('hdf5')]
1237+
call exe%test_serialization('executable_config: 3',error)
1238+
1239+
call dependency_destroy(dep)
1240+
1241+
dep%name = "M_CLI2"
1242+
dep%path = "~/./some/dummy/path"
1243+
dep%namespace = "urbanjost"
1244+
allocate(dep%requested_version)
1245+
call new_version(dep%requested_version, "3.2.0",error); if (allocated(error)) return
1246+
1247+
allocate(dep%git)
1248+
dep%git = git_target_revision(url="https://github.com/urbanjost/M_CLI2.git", &
1249+
sha1="7264878cdb1baff7323cc48596d829ccfe7751b8")
1250+
1251+
allocate(exe%dependency(1),source=dep)
1252+
call exe%test_serialization('executable_config: 4',error)
1253+
1254+
end subroutine executable_config_roundtrip
1255+
12151256
end module test_toml

0 commit comments

Comments
 (0)