Skip to content

Commit 3f511db

Browse files
authored
MPI: check presence of a runner command only with run and test apps (#937)
2 parents ee397ac + d8efee4 commit 3f511db

File tree

4 files changed

+97
-36
lines changed

4 files changed

+97
-36
lines changed

src/fpm.f90

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,8 @@ subroutine cmd_run(settings,test)
544544
end if
545545
end if
546546

547+
548+
547549
! Check all names are valid
548550
! or no name and found more than one file
549551
toomany= size(settings%name)==0 .and. size(executables)>1
@@ -588,10 +590,10 @@ subroutine cmd_run(settings,test)
588590
if (exists(executables(i)%s)) then
589591
if(settings%runner /= ' ')then
590592
if(.not.allocated(settings%args))then
591-
call run(settings%runner//' '//executables(i)%s, &
593+
call run(settings%runner_command()//' '//executables(i)%s, &
592594
echo=settings%verbose, exitstat=stat(i))
593595
else
594-
call run(settings%runner//' '//executables(i)%s//" "//settings%args, &
596+
call run(settings%runner_command()//' '//executables(i)%s//" "//settings%args, &
595597
echo=settings%verbose, exitstat=stat(i))
596598
endif
597599
else

src/fpm_command_line.f90

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ module fpm_command_line
2828
OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD
2929
use M_CLI2, only : set_args, lget, sget, unnamed, remaining, specified
3030
use M_CLI2, only : get_subcommand, CLI_RESPONSE_FILE
31-
use fpm_strings, only : lower, split, to_fortran_name, is_fortran_name
31+
use fpm_strings, only : lower, split, to_fortran_name, is_fortran_name, remove_characters_in_set, string_t
3232
use fpm_filesystem, only : basename, canon_path, which, run
3333
use fpm_environment, only : get_command_arguments_quoted
3434
use fpm_error, only : fpm_stop, error_t
@@ -88,9 +88,12 @@ module fpm_command_line
8888

8989
type, extends(fpm_build_settings) :: fpm_run_settings
9090
character(len=ibug),allocatable :: name(:)
91-
character(len=:),allocatable :: args
91+
character(len=:),allocatable :: args ! passed to the app
9292
character(len=:),allocatable :: runner
93+
character(len=:),allocatable :: runner_args ! passed to the runner
9394
logical :: example
95+
contains
96+
procedure :: runner_command
9497
end type
9598

9699
type, extends(fpm_run_settings) :: fpm_test_settings
@@ -139,7 +142,7 @@ module fpm_command_line
139142
& 'test', 'runner', 'install', 'update', 'list', 'help', 'version', 'publish' ]
140143

141144
character(len=:), allocatable :: val_runner, val_compiler, val_flag, val_cflag, val_cxxflag, val_ldflag, &
142-
val_profile
145+
val_profile, val_runner_args
143146

144147
! '12345678901234567890123456789012345678901234567890123456789012345678901234567890',&
145148
character(len=80), parameter :: help_text_build_common(*) = [character(len=80) :: &
@@ -264,7 +267,8 @@ subroutine get_command_line_settings(cmd_settings)
264267
run_args = &
265268
' --target " "' // &
266269
' --list F' // &
267-
' --runner " "'
270+
' --runner " "' // &
271+
' --runner-args " "'
268272

269273
compiler_args = &
270274
' --profile " "' // &
@@ -313,12 +317,18 @@ subroutine get_command_line_settings(cmd_settings)
313317
if(names(i)=='..')names(i)='*'
314318
enddo
315319

320+
! If there are additional command-line arguments, remove the additional
321+
! double quotes which have been added by M_CLI2
322+
val_runner_args=sget('runner-args')
323+
call remove_characters_in_set(val_runner_args,set='"')
324+
316325
c_compiler = sget('c-compiler')
317326
cxx_compiler = sget('cxx-compiler')
318327
archiver = sget('archiver')
319328
allocate(fpm_run_settings :: cmd_settings)
320329
val_runner=sget('runner')
321330
if(specified('runner') .and. val_runner=='')val_runner='echo'
331+
322332
cmd_settings=fpm_run_settings(&
323333
& args=remaining,&
324334
& profile=val_profile,&
@@ -336,6 +346,7 @@ subroutine get_command_line_settings(cmd_settings)
336346
& build_tests=.false.,&
337347
& name=names,&
338348
& runner=val_runner,&
349+
& runner_args=val_runner_args, &
339350
& verbose=lget('verbose') )
340351

341352
case('build')
@@ -561,12 +572,18 @@ subroutine get_command_line_settings(cmd_settings)
561572
if(names(i)=='..')names(i)='*'
562573
enddo
563574

575+
! If there are additional command-line arguments, remove the additional
576+
! double quotes which have been added by M_CLI2
577+
val_runner_args=sget('runner-args')
578+
call remove_characters_in_set(val_runner_args,set='"')
579+
564580
c_compiler = sget('c-compiler')
565581
cxx_compiler = sget('cxx-compiler')
566582
archiver = sget('archiver')
567583
allocate(fpm_test_settings :: cmd_settings)
568584
val_runner=sget('runner')
569585
if(specified('runner') .and. val_runner=='')val_runner='echo'
586+
570587
cmd_settings=fpm_test_settings(&
571588
& args=remaining, &
572589
& profile=val_profile, &
@@ -584,6 +601,7 @@ subroutine get_command_line_settings(cmd_settings)
584601
& build_tests=.true., &
585602
& name=names, &
586603
& runner=val_runner, &
604+
& runner_args=val_runner_args, &
587605
& verbose=lget('verbose'))
588606

589607
case('update')
@@ -762,7 +780,7 @@ subroutine set_help()
762780
' executables. ', &
763781
' ', &
764782
'SYNOPSIS ', &
765-
' fpm run|test --runner CMD ... -- SUFFIX_OPTIONS ', &
783+
' fpm run|test --runner CMD ... --runner-args ARGS -- SUFFIX_OPTIONS ', &
766784
' ', &
767785
'DESCRIPTION ', &
768786
' The --runner option allows specifying a program to launch ', &
@@ -778,8 +796,11 @@ subroutine set_help()
778796
' Available for both the "run" and "test" subcommands. ', &
779797
' If the keyword is specified without a value the default command ', &
780798
' is "echo". ', &
799+
' --runner-args "args" an additional option to pass command-line arguments ', &
800+
' to the runner command, instead of to the fpm app. ', &
781801
' -- SUFFIX_OPTIONS additional options to suffix the command CMD and executable ', &
782-
' file names with. ', &
802+
' file names with. These options are passed as command-line ', &
803+
' arguments to the app. ', &
783804
'EXAMPLES ', &
784805
' Use cases for ''fpm run|test --runner "CMD"'' include employing ', &
785806
' the following common GNU/Linux and Unix commands: ', &
@@ -808,6 +829,7 @@ subroutine set_help()
808829
' ', &
809830
' fpm test --runner gdb ', &
810831
' fpm run --runner "tar cvfz $HOME/bundle.tgz" ', &
832+
' fpm run --runner "mpiexec" --runner-args "-np 12" ', &
811833
' fpm run --runner ldd ', &
812834
' fpm run --runner strip ', &
813835
' fpm run --runner ''cp -t /usr/local/bin'' ', &
@@ -1424,4 +1446,20 @@ function get_fpm_env(env, default) result(val)
14241446
val = get_env(fpm_prefix//env, default)
14251447
end function get_fpm_env
14261448

1449+
1450+
!> Build a full runner command (executable + command-line arguments)
1451+
function runner_command(cmd) result(run_cmd)
1452+
class(fpm_run_settings), intent(in) :: cmd
1453+
character(len=:), allocatable :: run_cmd
1454+
!> Get executable
1455+
if (len_trim(cmd%runner)>0) then
1456+
run_cmd = trim(cmd%runner)
1457+
else
1458+
run_cmd = ''
1459+
end if
1460+
!> Append command-line arguments
1461+
if (len_trim(cmd%runner_args)>0) run_cmd = run_cmd//' '//trim(cmd%runner_args)
1462+
end function runner_command
1463+
1464+
14271465
end module fpm_command_line

src/fpm_meta.f90

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -293,11 +293,8 @@ subroutine resolve_cmd(self,settings,error)
293293
select type (cmd=>settings)
294294
class is (fpm_run_settings) ! includes fpm_test_settings
295295

296-
if (.not.allocated(cmd%runner)) then
297-
cmd%runner = self%run_command%s
298-
else
299-
cmd%runner = self%run_command%s//' '//cmd%runner
300-
end if
296+
! Only override runner if user has not provided a custom one
297+
if (.not.len_trim(cmd%runner)>0) cmd%runner = self%run_command%s
301298

302299
end select
303300

@@ -416,6 +413,15 @@ subroutine add_metapackage_model(model,package,settings,name,error)
416413
call meta%resolve(settings,error)
417414
if (allocated(error)) return
418415

416+
! If we need to run executables, there should be an MPI runner
417+
if (name=="mpi") then
418+
select type (settings)
419+
class is (fpm_run_settings) ! run, test
420+
if (.not.meta%has_run_command) &
421+
call fatal_error(error,"cannot find a valid mpi runner on the local host")
422+
end select
423+
endif
424+
419425
end subroutine add_metapackage_model
420426

421427
!> Resolve all metapackages into the package config
@@ -859,7 +865,7 @@ subroutine get_mpi_runner(command,verbose,error)
859865

860866
! Try several commands
861867
do itri=1,size(try)
862-
call find_command_location(trim(try(itri)),command%s,verbose=.true.,error=error)
868+
call find_command_location(trim(try(itri)),command%s,verbose=verbose,error=error)
863869
if (allocated(error)) cycle
864870

865871
! Success!
@@ -971,6 +977,7 @@ subroutine init_mpi_from_wrappers(this,compiler,mpilib,fort_wrapper,c_wrapper,cx
971977
type(error_t), allocatable, intent(out) :: error
972978

973979
type(version_t) :: version
980+
type(error_t), allocatable :: runner_error
974981

975982
! Cleanup structure
976983
call destroy(this)
@@ -1009,9 +1016,8 @@ subroutine init_mpi_from_wrappers(this,compiler,mpilib,fort_wrapper,c_wrapper,cx
10091016
end if
10101017

10111018
!> Add default run command, if present
1012-
this%run_command = mpi_wrapper_query(mpilib,fort_wrapper,'runner',verbose,error)
1013-
if (allocated(error)) return
1014-
this%has_run_command = len_trim(this%run_command)>0
1019+
this%run_command = mpi_wrapper_query(mpilib,fort_wrapper,'runner',verbose,runner_error)
1020+
this%has_run_command = (len_trim(this%run_command)>0) .and. .not.allocated(runner_error)
10151021

10161022
contains
10171023

@@ -1067,7 +1073,7 @@ subroutine mpi_compiler_match(language,wrappers,compiler,which_one,mpilib,error)
10671073
select case (language)
10681074
case (LANG_FORTRAN)
10691075
! Build compiler type. The ID is created based on the Fortran name
1070-
call new_compiler(mpi_compiler,screen%s,'','',echo=.true.,verbose=.true.)
1076+
call new_compiler(mpi_compiler,screen%s,'','',echo=.true.,verbose=.false.)
10711077

10721078
! Fortran match found!
10731079
if (mpi_compiler%id == compiler%id) then

src/fpm_strings.f90

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ module fpm_strings
4444
public :: to_fortran_name, is_fortran_name
4545
public :: string_array_contains, string_cat, len_trim, operator(.in.), fnv_1a
4646
public :: replace, resize, str, join, glob
47-
public :: notabs, dilate, remove_newline_characters
47+
public :: notabs, dilate, remove_newline_characters, remove_characters_in_set
4848

4949
!> Module naming
5050
public :: is_valid_module_name, is_valid_module_prefix, &
@@ -1221,44 +1221,59 @@ logical function has_valid_standard_prefix(module_name,package_name) result(vali
12211221

12221222
end function has_valid_standard_prefix
12231223

1224-
! Remove all new line characters from the current string, replace them with spaces
1225-
subroutine remove_newline_characters(string)
1226-
type(string_t), intent(inout) :: string
1224+
! Remove all characters from a set from a string
1225+
subroutine remove_characters_in_set(string,set,replace_with)
1226+
character(len=:), allocatable, intent(inout) :: string
1227+
character(*), intent(in) :: set
1228+
character, optional, intent(in) :: replace_with ! Replace with this character instead of removing
12271229

12281230
integer :: feed,length
12291231

1230-
character(*), parameter :: CRLF = new_line('a')//achar(13)
1231-
character(*), parameter :: SPACE = ' '
1232+
if (.not.allocated(string)) return
1233+
if (len(set)<=0) return
12321234

1233-
if (.not.allocated(string%s)) return
1234-
1235-
1236-
length = len(string%s)
1237-
feed = scan(string%s,CRLF)
1235+
length = len(string)
1236+
feed = scan(string,set)
12381237

12391238
do while (length>0 .and. feed>0)
12401239

12411240
! Remove heading
12421241
if (length==1) then
1243-
string = string_t("")
1242+
string = ""
12441243

12451244
elseif (feed==1) then
1246-
string%s = string%s(2:length)
1245+
string = string(2:length)
12471246

12481247
! Remove trailing
12491248
elseif (feed==length) then
1250-
string%s = string%s(1:length-1)
1249+
string = string(1:length-1)
12511250

1252-
! In between: replace with space
1251+
! In between: replace with given character
1252+
elseif (present(replace_with)) then
1253+
string(feed:feed) = replace_with
1254+
! Or just remove
12531255
else
1254-
string%s(feed:feed) = SPACE
1256+
string = string(1:feed-1)//string(feed+1:length)
12551257
end if
12561258

1257-
length = len(string%s)
1258-
feed = scan(string%s,CRLF)
1259+
length = len(string)
1260+
feed = scan(string,set)
12591261

12601262
end do
12611263

1264+
end subroutine remove_characters_in_set
1265+
1266+
! Remove all new line characters from the current string, replace them with spaces
1267+
subroutine remove_newline_characters(string)
1268+
type(string_t), intent(inout) :: string
1269+
1270+
integer :: feed,length
1271+
1272+
character(*), parameter :: CRLF = new_line('a')//achar(13)
1273+
character(*), parameter :: SPACE = ' '
1274+
1275+
call remove_characters_in_set(string%s,set=CRLF,replace_with=SPACE)
1276+
12621277
end subroutine remove_newline_characters
12631278

12641279
!>AUTHOR: John S. Urban

0 commit comments

Comments
 (0)