Skip to content

Commit

Permalink
Add support for toggling Fortran features (#864)
Browse files Browse the repository at this point in the history
- implicit-typing: toggle default implicit typing rules
  - option to disable in GFortran
  - option to enable in LFortran
- implicit-external: toggle implicit external interfaces
  - option to disable in GFortran
  - option to enable in LFortran
- source-form: select source form ("free", "fixed", or "default")
  - option to set free/fixed form in GFortran
  - option to set fixed form in LFortran
  • Loading branch information
awvwgk authored Apr 7, 2023
1 parent 55d94b0 commit ef6532b
Show file tree
Hide file tree
Showing 19 changed files with 368 additions and 12 deletions.
8 changes: 8 additions & 0 deletions ci/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ pushd cpp_files
"$fpm" test
popd

# Test Fortran features
for feature in free-form fixed-form implicit-typing implicit-external
do
pushd $feature
"$fpm" run
popd
done

# Test app exit codes
pushd fpm_test_exit_code
"$fpm" build
Expand Down
4 changes: 4 additions & 0 deletions example_packages/fixed-form/app/main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
program test
use lib
call hello
end
2 changes: 2 additions & 0 deletions example_packages/fixed-form/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name = "fixed-form"
fortran.source-form = "fixed"
7 changes: 7 additions & 0 deletions example_packages/fixed-form/src/lib.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module lib
contains
subroutine h e l l o
print '(a)',
+"Hello, fixed world!"
end subroutine
end module
4 changes: 4 additions & 0 deletions example_packages/free-form/app/main.f
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
program test
use lib
call hello
end
3 changes: 3 additions & 0 deletions example_packages/free-form/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name = "free-form"
fortran.source-form = "free"
executable = [{main="main.f", name="free-form"}]
6 changes: 6 additions & 0 deletions example_packages/free-form/src/lib.f
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module lib
contains
subroutine hello
print '(a)', "Hello, free world!"
end subroutine
end module
5 changes: 5 additions & 0 deletions example_packages/implicit-external/app/main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
program test
integer :: ijk
call impl(ijk)
if (ijk /= 1) error stop
end program test
2 changes: 2 additions & 0 deletions example_packages/implicit-external/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name = "implicit-external"
fortran.implicit-external = true
4 changes: 4 additions & 0 deletions example_packages/implicit-external/src/impl.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
subroutine impl(ijk)
integer :: ijk
ijk = 1
end subroutine impl
4 changes: 4 additions & 0 deletions example_packages/implicit-typing/app/main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
program test
use impl
if (ijk /= 1) error stop
end program
2 changes: 2 additions & 0 deletions example_packages/implicit-typing/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name = "implicit-typing"
fortran.implicit-typing = true
3 changes: 3 additions & 0 deletions example_packages/implicit-typing/src/impl.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module impl
parameter(ijk = 1)
end module
7 changes: 6 additions & 1 deletion src/fpm.f90
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module fpm
use fpm_environment, only: get_env
use fpm_filesystem, only: is_dir, join_path, list_files, exists, &
basename, filewrite, mkdir, run, os_delete_dir
use fpm_model, only: fpm_model_t, srcfile_t, show_model, &
use fpm_model, only: fpm_model_t, srcfile_t, show_model, fortran_features_t, &
FPM_SCOPE_UNKNOWN, FPM_SCOPE_LIB, FPM_SCOPE_DEP, &
FPM_SCOPE_APP, FPM_SCOPE_EXAMPLE, FPM_SCOPE_TEST
use fpm_compiler, only: new_compiler, new_archiver, set_cpp_preprocessor_flags
Expand Down Expand Up @@ -112,6 +112,11 @@ subroutine build_model(model, settings, package, error)
if (allocated(error)) exit

model%packages(i)%name = dependency%name
associate(features => model%packages(i)%features)
features%implicit_typing = dependency%fortran%implicit_typing
features%implicit_external = dependency%fortran%implicit_external
features%source_form = dependency%fortran%source_form
end associate
call package%version%to_string(version)
model%packages(i)%version = version

Expand Down
105 changes: 105 additions & 0 deletions src/fpm/manifest/fortran.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
module fpm_manifest_fortran
use fpm_error, only : error_t, syntax_error, fatal_error
use fpm_toml, only : toml_table, toml_key, toml_stat, get_value
implicit none
private

public :: fortran_config_t, new_fortran_config

!> Configuration data for Fortran
type :: fortran_config_t

!> Enable default implicit typing
logical :: implicit_typing

!> Enable implicit external interfaces
logical :: implicit_external

!> Form to use for all Fortran sources
character(:), allocatable :: source_form

end type fortran_config_t

contains

!> Construct a new build configuration from a TOML data structure
subroutine new_fortran_config(self, table, error)

!> Instance of the fortran configuration
type(fortran_config_t), intent(out) :: self

!> Instance of the TOML data structure
type(toml_table), intent(inout) :: table

!> Error handling
type(error_t), allocatable, intent(out) :: error

integer :: stat
character(:), allocatable :: source_form

call check(table, error)
if (allocated(error)) return

call get_value(table, "implicit-typing", self%implicit_typing, .false., stat=stat)

if (stat /= toml_stat%success) then
call fatal_error(error,"Error while reading value for 'implicit-typing' in fpm.toml, expecting logical")
return
end if

call get_value(table, "implicit-external", self%implicit_external, .false., stat=stat)

if (stat /= toml_stat%success) then
call fatal_error(error,"Error while reading value for 'implicit-external' in fpm.toml, expecting logical")
return
end if

call get_value(table, "source-form", source_form, "free", stat=stat)

if (stat /= toml_stat%success) then
call fatal_error(error,"Error while reading value for 'source-form' in fpm.toml, expecting logical")
return
end if
select case(source_form)
case default
call fatal_error(error,"Value of source-form cannot be '"//source_form//"'")
return
case("free", "fixed", "default")
self%source_form = source_form
end select

end subroutine new_fortran_config

!> Check local schema for allowed entries
subroutine check(table, error)

!> Instance of the TOML data structure
type(toml_table), intent(inout) :: table

!> Error handling
type(error_t), allocatable, intent(out) :: error

type(toml_key), allocatable :: list(:)
integer :: ikey

call table%get_keys(list)

! table can be empty
if (size(list) < 1) return

do ikey = 1, size(list)
select case(list(ikey)%key)

case("implicit-typing", "implicit-external", "source-form")
continue

case default
call syntax_error(error, "Key "//list(ikey)%key//" is not allowed in fortran")
exit

end select
end do

end subroutine check

end module fpm_manifest_fortran
15 changes: 14 additions & 1 deletion src/fpm/manifest/package.f90
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
!>[profiles]
!>[build]
!>[install]
!>[fortran]
!>[[ executable ]]
!>[[ example ]]
!>[[ test ]]
Expand All @@ -38,6 +39,7 @@ module fpm_manifest_package
use fpm_manifest_profile, only : profile_config_t, new_profiles, get_default_profiles
use fpm_manifest_example, only : example_config_t, new_example
use fpm_manifest_executable, only : executable_config_t, new_executable
use fpm_manifest_fortran, only : fortran_config_t, new_fortran_config
use fpm_manifest_library, only : library_config_t, new_library
use fpm_manifest_install, only: install_config_t, new_install_config
use fpm_manifest_test, only : test_config_t, new_test
Expand Down Expand Up @@ -75,6 +77,9 @@ module fpm_manifest_package
!> Installation configuration data
type(install_config_t) :: install

!> Fortran meta data
type(fortran_config_t) :: fortran

!> Library meta data
type(library_config_t), allocatable :: library

Expand Down Expand Up @@ -173,6 +178,14 @@ subroutine new_package(self, table, root, error)
call new_install_config(self%install, child, error)
if (allocated(error)) return

call get_value(table, "fortran", child, requested=.true., stat=stat)
if (stat /= toml_stat%success) then
call fatal_error(error, "Type mismatch for fortran entry, must be a table")
return
end if
call new_fortran_config(self%fortran, child, error)
if (allocated(error)) return

call get_value(table, "version", version, "0")
call new_version(self%version, version, error)
if (allocated(error) .and. present(root)) then
Expand Down Expand Up @@ -328,7 +341,7 @@ subroutine check(table, error)
case("version", "license", "author", "maintainer", "copyright", &
& "description", "keywords", "categories", "homepage", "build", &
& "dependencies", "dev-dependencies", "profiles", "test", "executable", &
& "example", "library", "install", "extra", "preprocess")
& "example", "library", "install", "extra", "preprocess", "fortran")
continue

end select
Expand Down
Loading

0 comments on commit ef6532b

Please sign in to comment.