Skip to content

Add: external-modules key to build table for non-fpm modules #438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions manifest-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Every manifest file consists of the following sections:
Toggle automatic discovery of executables
- [*link*](#link-external-libraries):
Link with external dependencies
- [*external-modules*](#use-system-installed-modules):
Specify modules used that are not within your fpm package
- Target sections:
- [*library*](#library-configuration)
Configuration of the library target
Expand Down Expand Up @@ -353,6 +355,30 @@ In this case the order of the libraries matters:
link = ["blas", "lapack"]
```

## Use system-installed modules

To use modules that are not defined within your fpm package or its dependencies,
specify the module name using the *external-modules* key in the *build* table.

> __Important:__ *fpm* cannot automatically locate external module files; it is the responsibility
> of the user to specify the necessary include directories using compiler flags such that
> the compiler can locate external module files during compilation.

*Example:*

```toml
[build]
external-modules = "netcdf"
```

Multiple external modules can be specified as a list.

*Example:*

```toml
[build]
external-modules = ["netcdf", "h5lt"]
```

## Automatic target discovery

Expand Down
5 changes: 5 additions & 0 deletions src/fpm.f90
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ subroutine build_model(model, settings, package, error)

allocate(model%include_dirs(0))
allocate(model%link_libraries(0))
allocate(model%external_modules(0))

call new_dependency_tree(model%deps, cache=join_path("build", "cache.toml"))
call model%deps%add(package, error)
Expand Down Expand Up @@ -171,6 +172,10 @@ subroutine build_model(model, settings, package, error)
if (allocated(dependency%build%link)) then
model%link_libraries = [model%link_libraries, dependency%build%link]
end if

if (allocated(dependency%build%external_modules)) then
model%external_modules = [model%external_modules, dependency%build%external_modules]
end if
end associate
end do
if (allocated(error)) return
Expand Down
16 changes: 14 additions & 2 deletions src/fpm/manifest/build.f90
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ module fpm_manifest_build
!> Libraries to link against
type(string_t), allocatable :: link(:)

!> External modules to use
type(string_t), allocatable :: external_modules(:)

contains

!> Print information on this instance
Expand Down Expand Up @@ -87,6 +90,9 @@ subroutine new_build_config(self, table, error)
call get_value(table, "link", self%link, error)
if (allocated(error)) return

call get_value(table, "external-modules", self%external_modules, error)
if (allocated(error)) return

end subroutine new_build_config


Expand All @@ -110,7 +116,7 @@ subroutine check(table, error)
do ikey = 1, size(list)
select case(list(ikey)%key)

case("auto-executables", "auto-examples", "auto-tests", "link")
case("auto-executables", "auto-examples", "auto-tests", "link", "external-modules")
continue

case default
Expand All @@ -135,7 +141,7 @@ subroutine info(self, unit, verbosity)
!> Verbosity of the printout
integer, intent(in), optional :: verbosity

integer :: pr, ilink
integer :: pr, ilink, imod
character(len=*), parameter :: fmt = '("#", 1x, a, t30, a)'

if (present(verbosity)) then
Expand All @@ -156,6 +162,12 @@ subroutine info(self, unit, verbosity)
write(unit, fmt) " - " // self%link(ilink)%s
end do
end if
if (allocated(self%external_modules)) then
write(unit, fmt) " - external modules"
do imod = 1, size(self%external_modules)
write(unit, fmt) " - " // self%external_modules(imod)%s
end do
end if

end subroutine info

Expand Down
10 changes: 10 additions & 0 deletions src/fpm_model.f90
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ module fpm_model
!> Native libraries to link against
type(string_t), allocatable :: link_libraries(:)

!> External modules used
type(string_t), allocatable :: external_modules(:)

!> Project dependencies
type(dependency_tree_t) :: deps

Expand Down Expand Up @@ -276,6 +279,13 @@ function info_model(model) result(s)
if (i < size(model%link_libraries)) s = s // ", "
end do
s = s // "]"
! type(string_t), allocatable :: external_modules(:)
s = s // ", external_modules=["
do i = 1, size(model%external_modules)
s = s // '"' // model%external_modules(i)%s // '"'
if (i < size(model%external_modules)) s = s // ", "
end do
s = s // "]"
! type(dependency_tree_t) :: deps
! TODO: print `dependency_tree_t` properly, which should become part of the
! model, not imported from another file
Expand Down
10 changes: 8 additions & 2 deletions src/fpm_targets.f90
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ subroutine targets_from_sources(targets,model,error)

call build_target_list(targets,model)

call resolve_module_dependencies(targets,error)
call resolve_module_dependencies(targets,model%external_modules,error)
if (allocated(error)) return

call resolve_target_linking(targets,model)
Expand Down Expand Up @@ -345,8 +345,9 @@ end subroutine add_dependency
!> a source file in the package of the correct scope, then a __fatal error__
!> is returned by the procedure and model construction fails.
!>
subroutine resolve_module_dependencies(targets,error)
subroutine resolve_module_dependencies(targets,external_modules,error)
type(build_target_ptr), intent(inout), target :: targets(:)
type(string_t), intent(in) :: external_modules(:)
type(error_t), allocatable, intent(out) :: error

type(build_target_ptr) :: dep
Expand All @@ -364,6 +365,11 @@ subroutine resolve_module_dependencies(targets,error)
cycle
end if

if (targets(i)%ptr%source%modules_used(j)%s .in. external_modules) then
! Dependency satisfied in system-installed module
cycle
end if

if (any(targets(i)%ptr%source%unit_scope == &
[FPM_SCOPE_APP, FPM_SCOPE_EXAMPLE, FPM_SCOPE_TEST])) then
dep%ptr => &
Expand Down
9 changes: 9 additions & 0 deletions test/fpm_test/test_module_dependencies.f90
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ subroutine test_library_module_use(error)
type(build_target_ptr), allocatable :: targets(:)

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(2))

Expand Down Expand Up @@ -137,6 +138,7 @@ subroutine test_scope(exe_scope,error)
character(:), allocatable :: scope_str

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(2))

Expand Down Expand Up @@ -196,6 +198,7 @@ subroutine test_program_with_module(error)
type(build_target_ptr), allocatable :: targets(:)

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(1))

Expand Down Expand Up @@ -249,6 +252,7 @@ subroutine test_scope(exe_scope,error)
character(:), allocatable :: scope_str

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(3))

Expand Down Expand Up @@ -308,6 +312,7 @@ subroutine test_missing_library_use(error)
type(build_target_ptr), allocatable :: targets(:)

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(2))

Expand Down Expand Up @@ -335,6 +340,7 @@ subroutine test_missing_program_use(error)
type(build_target_ptr), allocatable :: targets(:)

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(2))

Expand All @@ -361,6 +367,7 @@ subroutine test_invalid_library_use(error)
type(build_target_ptr), allocatable :: targets(:)

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(2))

Expand Down Expand Up @@ -388,6 +395,7 @@ subroutine test_subdirectory_module_use(error)
type(build_target_ptr), allocatable :: targets(:)

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(2))

Expand Down Expand Up @@ -507,6 +515,7 @@ subroutine test_invalid_subdirectory_module_use(error)
type(build_target_ptr), allocatable :: targets(:)

model%output_directory = ''
allocate(model%external_modules(0))
allocate(model%packages(1))
allocate(model%packages(1)%sources(2))

Expand Down