Skip to content
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

Feat: option to install test programs #1079

Merged
merged 7 commits into from
Oct 23, 2024
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
34 changes: 30 additions & 4 deletions src/fpm/cmd/install.f90
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module fpm_cmd_install
use fpm_filesystem, only : join_path, list_files
use fpm_installer, only : installer_t, new_installer
use fpm_manifest, only : package_config_t, get_package_data
use fpm_model, only : fpm_model_t, FPM_SCOPE_APP
use fpm_model, only : fpm_model_t, FPM_SCOPE_APP, FPM_SCOPE_TEST
use fpm_targets, only: targets_from_sources, build_target_t, &
build_target_ptr, FPM_TARGET_EXECUTABLE, &
filter_library_targets, filter_executable_targets, filter_modules
Expand All @@ -34,7 +34,7 @@ subroutine cmd_install(settings)

call get_package_data(package, "fpm.toml", error, apply_defaults=.true.)
call handle_error(error)

call build_model(model, settings, package, error)
call handle_error(error)

Expand All @@ -57,7 +57,7 @@ subroutine cmd_install(settings)
end if

call new_installer(installer, prefix=settings%prefix, &
bindir=settings%bindir, libdir=settings%libdir, &
bindir=settings%bindir, libdir=settings%libdir, testdir=settings%testdir, &
includedir=settings%includedir, &
verbosity=merge(2, 1, settings%verbose))

Expand All @@ -72,12 +72,19 @@ subroutine cmd_install(settings)
call handle_error(error)
end if
end if

if (allocated(package%executable) .or. ntargets>0) then
call install_executables(installer, targets, error)
call handle_error(error)
end if

if (allocated(package%test) .and. (package%install%test .or. model%include_tests)) then

call install_tests(installer, targets, error)
call handle_error(error)

end if

end subroutine cmd_install

subroutine install_info(unit, verbose, targets, ntargets)
Expand All @@ -97,6 +104,9 @@ subroutine install_info(unit, verbose, targets, ntargets)
call filter_executable_targets(targets, FPM_SCOPE_APP, temp)
install_target = [install_target, temp]

call filter_executable_targets(targets, FPM_SCOPE_TEST, temp)
install_target = [install_target, temp]

ntargets = size(install_target)

if (verbose) then
Expand Down Expand Up @@ -144,6 +154,22 @@ subroutine install_executables(installer, targets, error)

end subroutine install_executables

subroutine install_tests(installer, targets, error)
type(installer_t), intent(inout) :: installer
type(build_target_ptr), intent(in) :: targets(:)
type(error_t), allocatable, intent(out) :: error
integer :: ii

do ii = 1, size(targets)
if (targets(ii)%ptr%is_executable_target(FPM_SCOPE_TEST)) then
call installer%install_test(targets(ii)%ptr%output_file, error)
if (allocated(error)) exit
end if
end do
if (allocated(error)) return

end subroutine install_tests

subroutine handle_error(error)
type(error_t), intent(in), optional :: error
if (present(error)) then
Expand Down
39 changes: 38 additions & 1 deletion src/fpm/installer.f90
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ module fpm_installer
character(len=:), allocatable :: bindir
!> Library directory relative to the installation prefix
character(len=:), allocatable :: libdir
!> Test program directory relative to the installation prefix
character(len=:), allocatable :: testdir
!> Include directory relative to the installation prefix
character(len=:), allocatable :: includedir
!> Output unit for informative printout
Expand All @@ -40,6 +42,8 @@ module fpm_installer
procedure :: install_library
!> Install a header/module in its correct subdirectory
procedure :: install_header
!> Install a test program in its correct subdirectory
procedure :: install_test
!> Install a generic file into a subdirectory in the installation prefix
procedure :: install
!> Run an installation command, type-bound for unit testing purposes
Expand All @@ -53,6 +57,9 @@ module fpm_installer

!> Default name of the library subdirectory
character(len=*), parameter :: default_libdir = "lib"

!> Default name of the test subdirectory
character(len=*), parameter :: default_testdir = "test"

!> Default name of the include subdirectory
character(len=*), parameter :: default_includedir = "include"
Expand All @@ -78,7 +85,7 @@ module fpm_installer
contains

!> Create a new instance of an installer
subroutine new_installer(self, prefix, bindir, libdir, includedir, verbosity, &
subroutine new_installer(self, prefix, bindir, libdir, includedir, testdir, verbosity, &
copy, move)
!> Instance of the installer
type(installer_t), intent(out) :: self
Expand All @@ -90,6 +97,8 @@ subroutine new_installer(self, prefix, bindir, libdir, includedir, verbosity, &
character(len=*), intent(in), optional :: libdir
!> Include directory relative to the installation prefix
character(len=*), intent(in), optional :: includedir
!> Test directory relative to the installation prefix
character(len=*), intent(in), optional :: testdir
!> Verbosity of the installer
integer, intent(in), optional :: verbosity
!> Copy command
Expand Down Expand Up @@ -125,6 +134,12 @@ subroutine new_installer(self, prefix, bindir, libdir, includedir, verbosity, &
else
self%includedir = default_includedir
end if

if (present(testdir)) then
self%testdir = testdir
else
self%testdir = default_testdir
end if

if (present(prefix)) then
self%prefix = prefix
Expand Down Expand Up @@ -186,6 +201,28 @@ subroutine install_library(self, library, error)
call self%install(library, self%libdir, error)
end subroutine install_library

!> Install a test program in its correct subdirectory
subroutine install_test(self, test, error)
!> Instance of the installer
class(installer_t), intent(inout) :: self
!> Path to the test executable
character(len=*), intent(in) :: test
!> Error handling
type(error_t), allocatable, intent(out) :: error
integer :: ll

if (.not.os_is_unix(self%os)) then
ll = len(test)
if (test(max(1, ll-3):ll) /= ".exe") then
call self%install(test//".exe", self%testdir, error)
return
end if
end if

call self%install(test, self%testdir, error)

end subroutine install_test

!> Install a header/module in its correct subdirectory
subroutine install_header(self, header, error)
!> Instance of the installer
Expand Down
19 changes: 15 additions & 4 deletions src/fpm/manifest/install.f90
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ module fpm_manifest_install

!> Install library with this project
logical :: library = .false.

!> Install tests with this project
logical :: test = .false.

contains

Expand Down Expand Up @@ -51,6 +54,7 @@ subroutine new_install_config(self, table, error)
if (allocated(error)) return

call get_value(table, "library", self%library, .false.)
call get_value(table, "test", self%test, .false.)

end subroutine new_install_config

Expand All @@ -75,8 +79,8 @@ subroutine check(table, error)
case default
call syntax_error(error, "Key "//list(ikey)%key//" is not allowed in install table")
exit
case("library")
continue
case("library","test")
continue
end select
end do
if (allocated(error)) return
Expand Down Expand Up @@ -107,8 +111,8 @@ subroutine info(self, unit, verbosity)
if (pr < 1) return

write(unit, fmt) "Install configuration"
write(unit, fmt) " - library install", &
& trim(merge("enabled ", "disabled", self%library))
write(unit, fmt) " - library install", trim(merge("enabled ", "disabled", self%library))
write(unit, fmt) " - test install", trim(merge("enabled ", "disabled", self%test))

end subroutine info

Expand All @@ -121,6 +125,7 @@ logical function install_conf_same(this,that)
select type (other=>that)
type is (install_config_t)
if (this%library.neqv.other%library) return
if (this%test.neqv.other%test) return
class default
! Not the same type
return
Expand All @@ -144,6 +149,10 @@ subroutine dump_to_toml(self, table, error)
type(error_t), allocatable, intent(out) :: error

call set_value(table, "library", self%library, error, class_name)
if (allocated(error)) return

call set_value(table, "test", self%test, error, class_name)
if (allocated(error)) return

end subroutine dump_to_toml

Expand All @@ -163,6 +172,8 @@ subroutine load_from_toml(self, table, error)

call get_value(table, "library", self%library, error, class_name)
if (allocated(error)) return
call get_value(table, "test", self%test, error, class_name)
if (allocated(error)) return

end subroutine load_from_toml

Expand Down
12 changes: 10 additions & 2 deletions src/fpm_command_line.f90
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ module fpm_command_line
character(len=:), allocatable :: prefix
character(len=:), allocatable :: bindir
character(len=:), allocatable :: libdir
character(len=:), allocatable :: testdir
character(len=:), allocatable :: includedir
logical :: no_rebuild
end type
Expand Down Expand Up @@ -533,8 +534,8 @@ subroutine get_command_line_settings(cmd_settings)
case('install')
call set_args(common_args // compiler_args // '&
& --no-rebuild F --prefix " " &
& --list F &
& --libdir "lib" --bindir "bin" --includedir "include"', &
& --list F --test F &
& --libdir "lib" --bindir "bin" --testdir "test" --includedir "include"', &
help_install, version_text)

call check_build_vals()
Expand All @@ -544,6 +545,7 @@ subroutine get_command_line_settings(cmd_settings)
archiver = sget('archiver')
allocate(install_settings, source=fpm_install_settings(&
list=lget('list'), &
build_tests=lget('test'), &
profile=val_profile,&
prune=.not.lget('no-prune'), &
compiler=val_compiler, &
Expand All @@ -558,6 +560,7 @@ subroutine get_command_line_settings(cmd_settings)
verbose=lget('verbose')))
call get_char_arg(install_settings%prefix, 'prefix')
call get_char_arg(install_settings%libdir, 'libdir')
call get_char_arg(install_settings%testdir, 'testdir')
call get_char_arg(install_settings%bindir, 'bindir')
call get_char_arg(install_settings%includedir, 'includedir')
call move_alloc(install_settings, cmd_settings)
Expand Down Expand Up @@ -1418,6 +1421,7 @@ subroutine set_help()
help_text_build_common,&
help_text_flag, &
' --no-rebuild do not rebuild project before installation', &
' --test also install test programs', &
' --prefix DIR path to installation directory (requires write access),', &
' the default prefix on Unix systems is $HOME/.local', &
' and %APPDATA%\local on Windows', &
Expand All @@ -1426,6 +1430,7 @@ subroutine set_help()
' (default: lib)', &
' --includedir DIR subdirectory to place headers and module files in', &
' (default: include)', &
' --testdir DIR subdirectory to place test programs in (default: test)', &
' --verbose print more information', &
'', &
help_text_environment, &
Expand All @@ -1442,6 +1447,9 @@ subroutine set_help()
' 3. Install executables to a custom prefix into the exe directory:', &
'', &
' fpm install --prefix $PWD --bindir exe', &
' 4. Install executables and test programs into the same "exe" directory:', &
'', &
' fpm install --prefix $PWD --test --bindir exe --testdir exe', &
'' ]
help_clean=[character(len=80) :: &
'NAME', &
Expand Down
38 changes: 37 additions & 1 deletion test/fpm_test/test_installer.f90
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ subroutine collect_installer(testsuite)
& new_unittest("install-sitepackages", test_install_sitepackages), &
& new_unittest("install-mod", test_install_mod), &
& new_unittest("install-exe-unix", test_install_exe_unix), &
& new_unittest("install-exe-win", test_install_exe_win)]
& new_unittest("install-exe-win", test_install_exe_win), &
& new_unittest("install-test-unix", test_install_tests_unix), &
& new_unittest("install-test-win", test_install_tests_win)]

end subroutine collect_installer

Expand Down Expand Up @@ -73,6 +75,40 @@ subroutine test_install_exe_win(error)

end subroutine test_install_exe_win

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

type(mock_installer_t) :: mock
type(installer_t) :: installer

call new_installer(installer, prefix="PREFIX", testdir="tdir", verbosity=0, copy="mock")
mock%installer_t = installer
mock%os = OS_LINUX
mock%expected_dir = "PREFIX/tdir"
mock%expected_run = 'mock "name" "'//mock%expected_dir//'"'

call mock%install_test("name", error)

end subroutine test_install_tests_unix

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

type(mock_installer_t) :: mock
type(installer_t) :: installer

call new_installer(installer, prefix="PREFIX", testdir="tdir", verbosity=0, copy="mock")
mock%installer_t = installer
mock%os = OS_WINDOWS
mock%expected_dir = "PREFIX\tdir"
mock%expected_run = 'mock "name.exe" "'//mock%expected_dir//'"'

call mock%install_test("name", error)

end subroutine test_install_tests_win

subroutine test_install_lib(error)
!> Error handling
type(error_t), allocatable, intent(out) :: error
Expand Down
Loading