aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fpm/src/fpm.f90682
-rw-r--r--fpm/src/fpm_command_line.f90744
2 files changed, 707 insertions, 719 deletions
diff --git a/fpm/src/fpm.f90 b/fpm/src/fpm.f90
index 7061d6d..7e96456 100644
--- a/fpm/src/fpm.f90
+++ b/fpm/src/fpm.f90
@@ -1,17 +1,17 @@
module fpm
-use fpm_strings, only : string_t, str_ends_with
-use fpm_backend, only : build_package
+use fpm_strings, only : string_t, str_ends_with
+use fpm_backend, only : build_package
use fpm_command_line, only : fpm_build_settings, fpm_new_settings, &
- fpm_run_settings, fpm_install_settings, fpm_test_settings
-use fpm_environment, only : run, get_os_type, OS_LINUX, OS_MACOS, OS_WINDOWS
-use fpm_filesystem, only : join_path, number_of_rows, list_files, exists, basename, mkdir
-use fpm_model, only : srcfile_ptr, srcfile_t, fpm_model_t
-use fpm_sources, only : add_executable_sources, add_sources_from_dir, &
- resolve_module_dependencies
-use fpm_manifest, only : get_package_data, default_executable, &
- default_library, package_t, default_test
-use fpm_error, only : error_t
+ fpm_run_settings, fpm_install_settings, fpm_test_settings
+use fpm_environment, only : run, get_os_type, OS_LINUX, OS_MACOS, OS_WINDOWS
+use fpm_filesystem, only : join_path, number_of_rows, list_files, exists, basename, mkdir
+use fpm_model, only : srcfile_ptr, srcfile_t, fpm_model_t
+use fpm_sources, only : add_executable_sources, add_sources_from_dir, &
+ resolve_module_dependencies
+use fpm_manifest, only : get_package_data, default_executable, &
+ default_library, package_t, default_test
+use fpm_error, only : error_t
use fpm_manifest_test, only : test_t
use,intrinsic :: iso_fortran_env, only : stdin=>input_unit, &
& stdout=>output_unit, &
@@ -21,9 +21,8 @@ private
public :: cmd_build, cmd_install, cmd_new, cmd_run, cmd_test
contains
-!===================================================================================================================================
-!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
-!===================================================================================================================================
+
+
subroutine build_model(model, settings, package, error)
! Constructs a valid fpm model from command line settings and toml manifest
!
@@ -41,13 +40,13 @@ subroutine build_model(model, settings, package, error)
if(settings%release)then
model%output_directory = 'build/gfortran_release'
model%fortran_compile_flags=' &
- & -O3 &
- & -Wimplicit-interface &
- & -fPIC &
- & -fmax-errors=1 &
- & -ffast-math &
- & -funroll-loops ' // &
- & '-J'//join_path(model%output_directory,model%package_name)
+ & -O3 &
+ & -Wimplicit-interface &
+ & -fPIC &
+ & -fmax-errors=1 &
+ & -ffast-math &
+ & -funroll-loops ' // &
+ & '-J'//join_path(model%output_directory,model%package_name)
else
model%output_directory = 'build/gfortran_debug'
model%fortran_compile_flags = ' -Wall -Wextra -Wimplicit-interface -fPIC -fmax-errors=1 -g '// &
@@ -60,123 +59,122 @@ subroutine build_model(model, settings, package, error)
if (allocated(package%executable)) then
call add_executable_sources(model%sources, package%executable, &
- is_test=.false., error=error)
+ is_test=.false., error=error)
if (allocated(error)) then
return
- end if
+ endif
- end if
+ endif
if (allocated(package%test)) then
call add_executable_sources(model%sources, package%test, &
- is_test=.true., error=error)
+ is_test=.true., error=error)
if (allocated(error)) then
return
- end if
+ endif
- end if
+ endif
if (allocated(package%library)) then
call add_sources_from_dir(model%sources,package%library%source_dir, &
- error=error)
+ error=error)
if (allocated(error)) then
return
- end if
+ endif
- end if
+ endif
if(settings%list)then
- do i=1,size(model%sources)
+ do i=1,size(model%sources)
write(stderr,'(*(g0,1x))')'fpm::build<INFO>:file expected at',model%sources(i)%file_name, &
- & merge('exists ','does not exist',exists(model%sources(i)%file_name) )
- enddo
- stop
+ & merge('exists ','does not exist',exists(model%sources(i)%file_name) )
+ enddo
+ stop
else
- call resolve_module_dependencies(model%sources)
+ call resolve_module_dependencies(model%sources)
endif
end subroutine build_model
-!===================================================================================================================================
-!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
-!===================================================================================================================================
+
+
subroutine cmd_build(settings)
type(fpm_build_settings), intent(in) :: settings
type(package_t) :: package
type(fpm_model_t) :: model
type(error_t), allocatable :: error
-call get_package_data(package, "fpm.toml", error)
-if (allocated(error)) then
- print '(a)', error%message
- error stop 1
-end if
-
-! Populate library in case we find the default src directory
-if (.not.allocated(package%library) .and. exists("src")) then
- allocate(package%library)
- call default_library(package%library)
-end if
-
-! Populate executable in case we find the default app directory
-if (.not.allocated(package%executable) .and. exists("app")) then
- allocate(package%executable(1))
- call default_executable(package%executable(1), package%name)
-end if
-
-! Populate test in case we find the default test directory
-if (.not.allocated(package%test) .and. exists("test")) then
- allocate(package%test(1))
- call default_test(package%test(1), package%name)
-end if
-
-if (.not.(allocated(package%library) .or. allocated(package%executable) .or. allocated(package%test) )) then
- print '(a)', "Neither library nor executable found, there is nothing to do"
- error stop 1
-end if
-
-call build_model(model, settings, package, error)
-if (allocated(error)) then
- print '(a)', error%message
- error stop 1
-end if
-
-call build_package(model)
+
+ call get_package_data(package, "fpm.toml", error)
+ if (allocated(error)) then
+ print '(a)', error%message
+ error stop 5
+ endif
+
+ ! Populate library in case we find the default src directory
+ if (.not.allocated(package%library) .and. exists("src")) then
+ allocate(package%library)
+ call default_library(package%library)
+ endif
+
+ ! Populate executable in case we find the default app directory
+ if (.not.allocated(package%executable) .and. exists("app")) then
+ allocate(package%executable(1))
+ call default_executable(package%executable(1), package%name)
+ endif
+
+ ! Populate test in case we find the default test directory
+ if (.not.allocated(package%test) .and. exists("test")) then
+ allocate(package%test(1))
+ call default_test(package%test(1), package%name)
+ endif
+
+ if (.not.(allocated(package%library) .or. allocated(package%executable) .or. allocated(package%test) )) then
+ print '(a)', "Neither library nor executable found, there is nothing to do"
+ error stop 6
+ endif
+
+ call build_model(model, settings, package, error)
+ if (allocated(error)) then
+ print '(a)', error%message
+ error stop 7
+ endif
+
+ call build_package(model)
end subroutine cmd_build
-!===================================================================================================================================
-!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
-!===================================================================================================================================
+
+
subroutine cmd_install(settings)
type(fpm_install_settings), intent(in) :: settings
print *, "fpm error: 'fpm install' not implemented."
- error stop 1
+ error stop 8
end subroutine cmd_install
-!===================================================================================================================================
-!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
-!===================================================================================================================================
+
+
subroutine cmd_new(settings) ! --with-executable F --with-test F '
type(fpm_new_settings), intent(in) :: settings
integer :: ierr
character(len=:),allocatable :: bname ! baeename of NAME
character(len=:),allocatable :: message(:)
character(len=:),allocatable :: littlefile(:)
- call mkdir(settings%name) ! make new directory
- call run('cd '//settings%name) ! change to new directory as a test. New OS routines to improve this; system dependent potentially
- !! NOTE: need some system routines to handle filenames like "." like realpath() or getcwd().
- bname=basename(settings%name)
- !! weird gfortran bug?? lines truncated to concatenated string length, not 80
- !! hit some weird gfortran bug when littlefile data was an argument to warnwrite(3f), ok when a variable
+ call mkdir(settings%name) ! make new directory
+ call run('cd '//settings%name) ! change to new directory as a test. New OS routines to improve this; system dependent potentially
+ !! NOTE: need some system routines to handle filenames like "." like realpath() or getcwd().
+ bname=basename(settings%name)
+
+ !! weird gfortran bug?? lines truncated to concatenated string length, not 80
+ !! hit some weird gfortran bug when littlefile data was an argument to warnwrite(3f), ok when a variable
call warnwrite(join_path(settings%name, '.gitignore'), ['build/*']) ! create NAME/.gitignore file
- littlefile=[character(len=80) :: '# '//bname, 'My cool new project!']
+ littlefile=[character(len=80) :: '# '//bname, 'My cool new project!']
- call warnwrite(join_path(settings%name, 'README.md'), littlefile) ! create NAME/README.md
+ call warnwrite(join_path(settings%name, 'README.md'), littlefile) ! create NAME/README.md
- message=[character(len=80) :: & ! start building NAME/fpm.toml
+ message=[character(len=80) :: & ! start building NAME/fpm.toml
&'name = "'//bname//'" ', &
&'version = "0.1.0" ', &
&'license = "license" ', &
@@ -186,81 +184,83 @@ character(len=:),allocatable :: littlefile(:)
&' ', &
&'']
- if(settings%with_lib)then
- call mkdir(join_path(settings%name,'src') )
- message=[character(len=80) :: message, & ! create next section of fpm.toml
- &'[library] ', &
- &'source-dir="src" ', &
- &'']
- littlefile=[character(len=80) :: & ! create placeholder module src/bname.f90
- &'module '//bname, &
- &' implicit none', &
- &' private', &
- &'', &
- &' public :: say_hello', &
- &'contains', &
- &' subroutine say_hello', &
- &' print *, "Hello, '//bname//'!"', &
- &' end subroutine say_hello', &
- &'end module '//bname]
- ! a proposed alternative default
- call warnwrite(join_path(settings%name, 'src', bname//'.f90'), littlefile) ! create NAME/src/NAME.f90
- endif
-
- if(settings%with_test)then
- call mkdir(join_path(settings%name, 'test')) ! create NAME/test or stop
- message=[character(len=80) :: message, & ! create next section of fpm.toml
- &'[[test]] ', &
- &'name="runTests" ', &
- &'source-dir="test" ', &
- &'main="main.f90" ', &
- &'']
-
- littlefile=[character(len=80) :: &
- &'program main', &
- &'implicit none', &
- &'', &
- &'print *, "Put some tests in here!"', &
- &'end program main']
- ! a proposed alternative default a little more substantive
- call warnwrite(join_path(settings%name, 'test/main.f90'), littlefile) ! create NAME/test/main.f90
- endif
-
- if(settings%with_executable)then
- call mkdir(join_path(settings%name, 'app')) ! create NAME/app or stop
- message=[character(len=80) :: message, & ! create next section of fpm.toml
- &'[[executable]] ', &
- &'name="'//bname//'" ', &
- &'source-dir="app" ', &
- &'main="main.f90" ', &
- &'']
-
- littlefile=[character(len=80) :: &
- &'program main', &
- &' use '//bname//', only: say_hello', &
- &'', &
- &' implicit none', &
- &'', &
- &' call say_hello', &
- &'end program main']
- call warnwrite(join_path(settings%name, 'app/main.f90'), littlefile)
- endif
-
- call warnwrite(join_path(settings%name, 'fpm.toml'), message) ! now that built it write NAME/fpm.toml
-
- call run('cd ' // settings%name // ';git init') ! assumes these commands work on all systems and git(1) is installed
+ if(settings%with_lib)then
+ call mkdir(join_path(settings%name,'src') )
+ message=[character(len=80) :: message, & ! create next section of fpm.toml
+ &'[library] ', &
+ &'source-dir="src" ', &
+ &'']
+ littlefile=[character(len=80) :: & ! create placeholder module src/bname.f90
+ &'module '//bname, &
+ &' implicit none', &
+ &' private', &
+ &'', &
+ &' public :: say_hello', &
+ &'contains', &
+ &' subroutine say_hello', &
+ &' print *, "Hello, '//bname//'!"', &
+ &' end subroutine say_hello', &
+ &'end module '//bname]
+ ! a proposed alternative default
+ call warnwrite(join_path(settings%name, 'src', bname//'.f90'), littlefile) ! create NAME/src/NAME.f90
+ endif
+
+ if(settings%with_test)then
+ call mkdir(join_path(settings%name, 'test')) ! create NAME/test or stop
+ message=[character(len=80) :: message, & ! create next section of fpm.toml
+ &'[[test]] ', &
+ &'name="runTests" ', &
+ &'source-dir="test" ', &
+ &'main="main.f90" ', &
+ &'']
+
+ littlefile=[character(len=80) :: &
+ &'program main', &
+ &'implicit none', &
+ &'', &
+ &'print *, "Put some tests in here!"', &
+ &'end program main']
+ ! a proposed alternative default a little more substantive
+ call warnwrite(join_path(settings%name, 'test/main.f90'), littlefile) ! create NAME/test/main.f90
+ endif
+
+ if(settings%with_executable)then
+ call mkdir(join_path(settings%name, 'app')) ! create NAME/app or stop
+ message=[character(len=80) :: message, & ! create next section of fpm.toml
+ &'[[executable]] ', &
+ &'name="'//bname//'" ', &
+ &'source-dir="app" ', &
+ &'main="main.f90" ', &
+ &'']
+
+ littlefile=[character(len=80) :: &
+ &'program main', &
+ &' use '//bname//', only: say_hello', &
+ &'', &
+ &' implicit none', &
+ &'', &
+ &' call say_hello', &
+ &'end program main']
+ call warnwrite(join_path(settings%name, 'app/main.f90'), littlefile)
+ endif
+
+ call warnwrite(join_path(settings%name, 'fpm.toml'), message) ! now that built it write NAME/fpm.toml
+
+ call run('cd ' // settings%name // ';git init') ! assumes these commands work on all systems and git(1) is installed
contains
-!===================================================================================================================================
+
subroutine warnwrite(fname,data)
character(len=*),intent(in) :: fname
character(len=*),intent(in) :: data(:)
- if(.not.exists(fname))then
- call filewrite(fname,data)
- else
- write(stderr,'(*(g0,1x))')'fpm::new<WARNING>',fname,'already exists. Not overwriting'
- endif
+
+ if(.not.exists(fname))then
+ call filewrite(fname,data)
+ else
+ write(stderr,'(*(g0,1x))')'fpm::new<WARNING>',fname,'already exists. Not overwriting'
+ endif
+
end subroutine warnwrite
-!===================================================================================================================================
+
subroutine filewrite(filename,filedata)
use,intrinsic :: iso_fortran_env, only : stdin=>input_unit, stdout=>output_unit, stderr=>error_unit
! write filedata to file filename
@@ -268,44 +268,44 @@ character(len=*),intent(in) :: filename
character(len=*),intent(in) :: filedata(:)
integer :: lun, i, ios
character(len=256) :: message
- message=' '
- ios=0
- if(filename.ne.' ')then
- open(file=filename, &
- & newunit=lun, &
- & form='formatted', & ! FORM = FORMATTED | UNFORMATTED
- & access='sequential', & ! ACCESS = SEQUENTIAL | DIRECT | STREAM
- & action='write', & ! ACTION = READ|WRITE | READWRITE
- & position='rewind', & ! POSITION = ASIS | REWIND | APPEND
- & status='new', & ! STATUS = NEW | REPLACE | OLD | SCRATCH | UNKNOWN
- & iostat=ios, &
- & iomsg=message)
- else
- lun=stdout
- ios=0
- endif
- if(ios.ne.0)then
- write(stderr,'(*(a,1x))')'*filewrite* error:',filename,trim(message)
- error stop 1
- endif
- do i=1,size(filedata) ! write file
- write(lun,'(a)',iostat=ios,iomsg=message)trim(filedata(i))
- if(ios.ne.0)then
- write(stderr,'(*(a,1x))')'*filewrite* error:',filename,trim(message)
- stop 4
- endif
- enddo
- close(unit=lun,iostat=ios,iomsg=message) ! close file
- if(ios.ne.0)then
- write(stderr,'(*(a,1x))')'*filewrite* error:',trim(message)
- error stop 2
- endif
+
+ message=' '
+ ios=0
+ if(filename.ne.' ')then
+ open(file=filename, &
+ & newunit=lun, &
+ & form='formatted', & ! FORM = FORMATTED | UNFORMATTED
+ & access='sequential', & ! ACCESS = SEQUENTIAL | DIRECT | STREAM
+ & action='write', & ! ACTION = READ|WRITE | READWRITE
+ & position='rewind', & ! POSITION = ASIS | REWIND | APPEND
+ & status='new', & ! STATUS = NEW | REPLACE | OLD | SCRATCH | UNKNOWN
+ & iostat=ios, &
+ & iomsg=message)
+ else
+ lun=stdout
+ ios=0
+ endif
+ if(ios.ne.0)then
+ write(stderr,'(*(a:,1x))')'*filewrite* error:',filename,trim(message)
+ error stop 1
+ endif
+ do i=1,size(filedata) ! write file
+ write(lun,'(a)',iostat=ios,iomsg=message)trim(filedata(i))
+ if(ios.ne.0)then
+ write(stderr,'(*(a:,1x))')'*filewrite* error:',filename,trim(message)
+ error stop 4
+ endif
+ enddo
+ close(unit=lun,iostat=ios,iomsg=message) ! close file
+ if(ios.ne.0)then
+ write(stderr,'(*(a:,1x))')'*filewrite* error:',trim(message)
+ error stop 2
+ endif
end subroutine filewrite
end subroutine cmd_new
-!===================================================================================================================================
-!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
-!===================================================================================================================================
+
+
subroutine cmd_run(settings)
type(fpm_run_settings), intent(in) :: settings
character(len=:),allocatable :: release_name, cmd, fname
@@ -315,82 +315,81 @@ type(error_t), allocatable :: error
character(len=:),allocatable :: newwords(:)
logical,allocatable :: foundit(:)
logical :: list
- call get_package_data(package, "fpm.toml", error)
- if (allocated(error)) then
- print '(a)', error%message
- stop
- endif
- release_name=trim(merge('gfortran_release','gfortran_debug ',settings%release))
- newwords=[character(len=0) ::]
- ! Populate executable in case we find the default app directory
- if (.not.allocated(package%executable) .and. exists("app")) then
- allocate(package%executable(1))
- call default_executable(package%executable(1), package%name)
- endif
- if(size(settings%name).eq.0)then
- if ( .not.allocated(package%executable) ) then
- write(stderr,'(*(g0,1x))')'fpm::run<INFO>:no executables found in fpm.toml and no default app/ directory'
- stop
- endif
- allocate(foundit(size(package%executable)))
- do i=1,size(package%executable)
- fname=join_path('build',release_name,package%executable(i)%source_dir,package%executable(i)%name)
- newwords=[character(len=max(len(newwords),len(fname))) :: newwords,fname]
- enddo
- if(size(newwords).lt.1)then
- write(stderr,'(*(g0,1x))')'fpm::run<INFO>:no executables found in fpm.toml'
- stop
- endif
- else
- !! expand names, duplicates are a problem??
- allocate(foundit(size(settings%name)))
- foundit=.false.
- FINDIT: do i=1,size(package%executable)
- do j=1,size(settings%name)
- if(settings%name(j).eq.package%executable(i)%name)then
- fname=join_path('build',release_name,package%executable(i)%source_dir,package%executable(i)%name)
- newwords=[character(len=max(len(newwords),len(fname))) :: newwords,fname]
- foundit(j)=.true.
+ call get_package_data(package, "fpm.toml", error)
+ if (allocated(error)) then
+ print '(a)', error%message
+ stop
+ endif
+ release_name=trim(merge('gfortran_release','gfortran_debug ',settings%release))
+ newwords=[character(len=0) ::]
+ ! Populate executable in case we find the default app directory
+ if (.not.allocated(package%executable) .and. exists("app")) then
+ allocate(package%executable(1))
+ call default_executable(package%executable(1), package%name)
+ endif
+ if(size(settings%name).eq.0)then
+ if ( .not.allocated(package%executable) ) then
+ write(stderr,'(*(g0,1x))')'fpm::run<INFO>:no executables found in fpm.toml and no default app/ directory'
+ stop
+ endif
+ allocate(foundit(size(package%executable)))
+ do i=1,size(package%executable)
+ fname=join_path('build',release_name,package%executable(i)%source_dir,package%executable(i)%name)
+ newwords=[character(len=max(len(newwords),len(fname))) :: newwords,fname]
+ enddo
+ if(size(newwords).lt.1)then
+ write(stderr,'(*(g0,1x))')'fpm::run<INFO>:no executables found in fpm.toml'
+ stop
+ endif
+ else
+ !! expand names, duplicates are a problem??
+ allocate(foundit(size(settings%name)))
+ foundit=.false.
+ FINDIT: do i=1,size(package%executable)
+ do j=1,size(settings%name)
+ if(settings%name(j).eq.package%executable(i)%name)then
+ fname=join_path('build',release_name,package%executable(i)%source_dir,package%executable(i)%name)
+ newwords=[character(len=max(len(newwords),len(fname))) :: newwords,fname]
+ foundit(j)=.true.
+ endif
+ enddo
+ enddo FINDIT
+ do i=1,size(settings%name)
+ if(.not.foundit(i))then
+ write(stderr,'(*(g0,1x))')'fpm::run<ERROR>:executable',trim(settings%name(i)),'not located'
+ !!elseif(settings%debug)then
+ !! write(stderr,'(*(g0,1x))')'fpm::run<INFO>:executable',trim(settings%name(i)),'located at',newwords(i),&
+ !! & merge('exists ','does not exist',exists(trim(settings%name(i))))
endif
- enddo
- enddo FINDIT
- do i=1,size(settings%name)
- if(.not.foundit(i))then
- write(stderr,'(*(g0,1x))')'fpm::run<ERROR>:executable',trim(settings%name(i)),'not located'
- !!elseif(settings%debug)then
- !! write(stderr,'(*(g0,1x))')'fpm::run<INFO>:executable',trim(settings%name(i)),'located at',newwords(i),&
- !! & merge('exists ','does not exist',exists(trim(settings%name(i))))
- endif
- enddo
- if(allocated(foundit))deallocate(foundit)
- endif
- do i=1,size(newwords)
- !! list is a new option for use with xargs, to move files to production area, valgrind, gdb, ls -l, ....
- !! maybe add as --mask and could do --mask 'echo %xx' or --mask 'cp %XX /usr/local/bin/' an so on
- !! default if blank would be filename uptodate|needs|updated|doesnotexist creation_date, ...
- !! or maybe just list filenames so can pipe through xargs, and so on
- if(settings%list)then
- write(stderr,'(*(g0,1x))')'fpm::run<INFO>:executable expected at',newwords(i),&
- & merge('exists ','does not exist',exists(newwords(i)))
- cycle
- endif
- cmd=newwords(i) // ' ' // settings%args
- if(exists(newwords(i)))then
- call run(cmd)
- else ! try to build -- once build works conditionally this should be an unconditional call
- call cmd_build(fpm_build_settings(release=settings%release,list=.false.))
- if(exists(newwords(i)))then
+ enddo
+ if(allocated(foundit))deallocate(foundit)
+ endif
+ do i=1,size(newwords)
+ !! list is a new option for use with xargs, to move files to production area, valgrind, gdb, ls -l, ....
+ !! maybe add as --mask and could do --mask 'echo %xx' or --mask 'cp %XX /usr/local/bin/' an so on
+ !! default if blank would be filename uptodate|needs|updated|doesnotexist creation_date, ...
+ !! or maybe just list filenames so can pipe through xargs, and so on
+ if(settings%list)then
+ write(stderr,'(*(g0,1x))')'fpm::run<INFO>:executable expected at',newwords(i),&
+ & merge('exists ','does not exist',exists(newwords(i)))
+ cycle
+ endif
+ cmd=newwords(i) // ' ' // settings%args
+ if(exists(newwords(i)))then
call run(cmd)
- else
- write(stderr,*)'fpm::run<ERROR>',cmd,' not found'
- endif
- endif
- enddo
- deallocate(newwords)
+ else ! try to build -- once build works conditionally this should be an unconditional call
+ call cmd_build(fpm_build_settings(release=settings%release,list=.false.))
+ if(exists(newwords(i)))then
+ call run(cmd)
+ else
+ write(stderr,*)'fpm::run<ERROR>',cmd,' not found'
+ endif
+ endif
+ enddo
+ deallocate(newwords)
end subroutine cmd_run
-!===================================================================================================================================
-!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
-!===================================================================================================================================
+
+
subroutine cmd_test(settings)
type(fpm_test_settings), intent(in) :: settings
character(len=:),allocatable :: release_name, cmd, fname
@@ -400,81 +399,80 @@ type(error_t), allocatable :: error
character(len=:),allocatable :: newwords(:)
logical,allocatable :: foundit(:)
logical :: list
- call get_package_data(package, "fpm.toml", error)
- if (allocated(error)) then
- print '(a)', error%message
- stop
- endif
- release_name=trim(merge('gfortran_release','gfortran_debug ',settings%release))
- newwords=[character(len=0) ::]
-
- ! Populate test in case we find the default test directory
- if (.not.allocated(package%test) .and. exists("test")) then
- allocate(package%test(1))
- call default_test(package%test(1), package%name)
- endif
- if(size(settings%name).eq.0)then
- if ( .not.allocated(package%test) ) then
- write(stderr,'(*(g0,1x))')'fpm::run<INFO>:no tests found in fpm.toml and no default test/ directory'
- stop
- endif
- allocate(foundit(size(package%test)))
- do i=1,size(package%test)
- fname=join_path('build',release_name,package%test(i)%source_dir,package%test(i)%name)
- newwords=[character(len=max(len(newwords),len(fname))) :: newwords,fname]
- enddo
- if(size(newwords).lt.1)then
- write(stderr,'(*(g0,1x))')'fpm::run<INFO>:no tests found in fpm.toml'
- stop
- endif
- else
- !! expand names, duplicates are a problem??
- allocate(foundit(size(settings%name)))
- foundit=.false.
- FINDIT: do i=1,size(package%test)
- do j=1,size(settings%name)
- if(settings%name(j).eq.package%test(i)%name)then
- fname=join_path('build',release_name,package%test(i)%source_dir,package%test(i)%name)
- newwords=[character(len=max(len(newwords),len(fname))) :: newwords,fname]
- foundit(j)=.true.
+ call get_package_data(package, "fpm.toml", error)
+ if (allocated(error)) then
+ print '(a)', error%message
+ stop
+ endif
+ release_name=trim(merge('gfortran_release','gfortran_debug ',settings%release))
+ newwords=[character(len=0) ::]
+
+ ! Populate test in case we find the default test directory
+ if (.not.allocated(package%test) .and. exists("test")) then
+ allocate(package%test(1))
+ call default_test(package%test(1), package%name)
+ endif
+ if(size(settings%name).eq.0)then
+ if ( .not.allocated(package%test) ) then
+ write(stderr,'(*(g0,1x))')'fpm::run<INFO>:no tests found in fpm.toml and no default test/ directory'
+ stop
+ endif
+ allocate(foundit(size(package%test)))
+ do i=1,size(package%test)
+ fname=join_path('build',release_name,package%test(i)%source_dir,package%test(i)%name)
+ newwords=[character(len=max(len(newwords),len(fname))) :: newwords,fname]
+ enddo
+ if(size(newwords).lt.1)then
+ write(stderr,'(*(g0,1x))')'fpm::run<INFO>:no tests found in fpm.toml'
+ stop
+ endif
+ else
+ !! expand names, duplicates are a problem??
+ allocate(foundit(size(settings%name)))
+ foundit=.false.
+ FINDIT: do i=1,size(package%test)
+ do j=1,size(settings%name)
+ if(settings%name(j).eq.package%test(i)%name)then
+ fname=join_path('build',release_name,package%test(i)%source_dir,package%test(i)%name)
+ newwords=[character(len=max(len(newwords),len(fname))) :: newwords,fname]
+ foundit(j)=.true.
+ endif
+ enddo
+ enddo FINDIT
+ do i=1,size(settings%name)
+ if(.not.foundit(i))then
+ write(stderr,'(*(g0,1x))')'fpm::run<ERROR>:test',trim(settings%name(i)),'not located'
+ !!elseif(settings%debug)then
+ !! write(stderr,'(*(g0,1x))')'fpm::run<INFO>:test',trim(settings%name(i)),'located at',newwords(i),&
+ !! & merge('exists ','does not exist',exists(trim(settings%name(i))))
endif
- enddo
- enddo FINDIT
- do i=1,size(settings%name)
- if(.not.foundit(i))then
- write(stderr,'(*(g0,1x))')'fpm::run<ERROR>:test',trim(settings%name(i)),'not located'
- !!elseif(settings%debug)then
- !! write(stderr,'(*(g0,1x))')'fpm::run<INFO>:test',trim(settings%name(i)),'located at',newwords(i),&
- !! & merge('exists ','does not exist',exists(trim(settings%name(i))))
- endif
- enddo
- if(allocated(foundit))deallocate(foundit)
- endif
- do i=1,size(newwords)
- !! list is a new option for use with xargs, to move files to production area, valgrind, gdb, ls -l, ....
- !! maybe add as --mask and could do --mask 'echo %xx' or --mask 'cp %XX /usr/local/bin/' an so on
- !! default if blank would be filename uptodate|needs|updated|doesnotexist creation_date, ...
- !! or maybe just list filenames so can pipe through xargs, and so on
- if(settings%list)then
- write(stderr,'(*(g0,1x))')'fpm::run<INFO>:test expected at',newwords(i),&
- & merge('exists ','does not exist',exists(newwords(i)))
- cycle
- endif
- cmd=newwords(i) // ' ' // settings%args
- if(exists(newwords(i)))then
- call run(cmd)
- else ! try to build -- once build works conditionally this should be an unconditional call
- call cmd_build(fpm_build_settings(release=settings%release,list=.false.))
- if(exists(newwords(i)))then
+ enddo
+ if(allocated(foundit))deallocate(foundit)
+ endif
+ do i=1,size(newwords)
+ !! list is a new option for use with xargs, to move files to production area, valgrind, gdb, ls -l, ....
+ !! maybe add as --mask and could do --mask 'echo %xx' or --mask 'cp %XX /usr/local/bin/' an so on
+ !! default if blank would be filename uptodate|needs|updated|doesnotexist creation_date, ...
+ !! or maybe just list filenames so can pipe through xargs, and so on
+ if(settings%list)then
+ write(stderr,'(*(g0,1x))')'fpm::run<INFO>:test expected at',newwords(i),&
+ & merge('exists ','does not exist',exists(newwords(i)))
+ cycle
+ endif
+ cmd=newwords(i) // ' ' // settings%args
+ if(exists(newwords(i)))then
call run(cmd)
- else
- write(stderr,*)'fpm::run<ERROR>',cmd,' not found'
- endif
- endif
- enddo
- deallocate(newwords)
+ else ! try to build -- once build works conditionally this should be an unconditional call
+ call cmd_build(fpm_build_settings(release=settings%release,list=.false.))
+ if(exists(newwords(i)))then
+ call run(cmd)
+ else
+ write(stderr,*)'fpm::run<ERROR>',cmd,' not found'
+ endif
+ endif
+ enddo
+ deallocate(newwords)
end subroutine cmd_test
-!===================================================================================================================================
-!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
-!===================================================================================================================================
+
+
end module fpm
diff --git a/fpm/src/fpm_command_line.f90 b/fpm/src/fpm_command_line.f90
index d1714bf..76bdca6 100644
--- a/fpm/src/fpm_command_line.f90
+++ b/fpm/src/fpm_command_line.f90
@@ -1,68 +1,58 @@
-!! new are full pathnames allowed? Is more than one pathname allowed?
-!! fpm --search search keywords, descriptions, names of fpm(1) package registry
-!! install not sure what it is supposed to do. Install files in build/ to a user-specified area?
-!! should test always write to build/test.log ?
-!! -list |xargs -iXX valgrind -options XX options?
-!! or maybe --mask "valgrind --options %XX --options"
-!! might be useful for valgrind, gdb, time, ...
-!! better to have commands in fpm.toml instead or in addition?
-!! what about profiling?
-!! note run and test are not currently doing an automatic build
module fpm_command_line
- use fpm_environment, only : get_os_type, &
- OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, &
- OS_CYGWIN, OS_SOLARIS, OS_FREEBSD
- use M_CLI2, only : set_args, lget, unnamed, remaining, specified
- use fpm_filesystem, only : basename
- use,intrinsic :: iso_fortran_env, only : stdin=>input_unit, &
+use fpm_environment, only : get_os_type, &
+ OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, &
+ OS_CYGWIN, OS_SOLARIS, OS_FREEBSD
+use M_CLI2, only : set_args, lget, unnamed, remaining, specified
+use fpm_filesystem, only : basename
+use,intrinsic :: iso_fortran_env, only : stdin=>input_unit, &
& stdout=>output_unit, &
& stderr=>error_unit
- implicit none
+implicit none
- private
- public :: fpm_cmd_settings, &
- fpm_build_settings, &
- fpm_install_settings, &
- fpm_new_settings, &
- fpm_run_settings, &
- fpm_test_settings, &
- get_command_line_settings
+private
+public :: fpm_cmd_settings, &
+ fpm_build_settings, &
+ fpm_install_settings, &
+ fpm_new_settings, &
+ fpm_run_settings, &
+ fpm_test_settings, &
+ get_command_line_settings
- type, abstract :: fpm_cmd_settings
- end type
+type, abstract :: fpm_cmd_settings
+end type
- integer,parameter :: ibug=4096
- type, extends(fpm_cmd_settings) :: fpm_new_settings
- character(len=:),allocatable :: name
- logical :: with_executable=.false.
- logical :: with_test=.false.
- logical :: with_lib=.true.
- end type
+integer,parameter :: ibug=4096
+type, extends(fpm_cmd_settings) :: fpm_new_settings
+ character(len=:),allocatable :: name
+ logical :: with_executable=.false.
+ logical :: with_test=.false.
+ logical :: with_lib=.true.
+end type
- type, extends(fpm_cmd_settings) :: fpm_build_settings
- logical :: release=.false.
- logical :: list=.false.
- end type
+type, extends(fpm_cmd_settings) :: fpm_build_settings
+ logical :: release=.false.
+ logical :: list=.false.
+end type
- type, extends(fpm_cmd_settings) :: fpm_run_settings
- character(len=ibug),allocatable :: name(:)
- logical :: release=.false.
- logical :: list=.false.
- character(len=:),allocatable :: args
- end type
+type, extends(fpm_cmd_settings) :: fpm_run_settings
+ character(len=ibug),allocatable :: name(:)
+ logical :: release=.false.
+ logical :: list=.false.
+ character(len=:),allocatable :: args
+end type
- type, extends(fpm_cmd_settings) :: fpm_test_settings
- character(len=ibug),allocatable :: name(:)
- logical :: release=.false.
- logical :: list=.false.
- character(len=:),allocatable :: args
- end type
+type, extends(fpm_cmd_settings) :: fpm_test_settings
+ character(len=ibug),allocatable :: name(:)
+ logical :: release=.false.
+ logical :: list=.false.
+ character(len=:),allocatable :: args
+end type
- type, extends(fpm_cmd_settings) :: fpm_install_settings
- end type
+type, extends(fpm_cmd_settings) :: fpm_install_settings
+end type
- character(len=:),allocatable :: name
- character(len=ibug),allocatable :: names(:)
+character(len=:),allocatable :: name
+character(len=ibug),allocatable :: names(:)
contains
subroutine get_command_line_settings(cmd_settings)
@@ -83,359 +73,359 @@ contains
! find the subcommand name by looking for first word on command not starting with dash
cmdarg = ''
do i = 1, command_argument_count()
- call get_command_argument(i, cmdarg)
- if(adjustl(cmdarg(1:1)) .ne. '-')exit
+ call get_command_argument(i, cmdarg)
+ if(adjustl(cmdarg(1:1)) .ne. '-')exit
enddo
! now set subcommand-specific help text and process commandline arguments. Then call subcommand routine
select case(trim(cmdarg))
case('run')
- help_text=[character(len=80) :: &
- 'NAME ', &
- ' run(1) - the fpm(1) subcommand to run project applications ', &
- ' ', &
- 'SYNOPSIS ', &
- ' fpm run [NAME(s)] [--release] [-- ARGS] ', &
- ' ', &
- ' fpm run --help|--version ', &
- ' ', &
- 'DESCRIPTION ', &
- ' Run applications you have built in your fpm(1) project. ', &
- ' ', &
- 'OPTIONS ', &
- ' NAME(s) optional list of specific names to execute. ', &
- ' The default is to run all the applications in app/ ', &
- ' or the programs listed in the "fpm.toml" file. ', &
- ' --release selects the optimized build instead of the debug ', &
- ' build. ', &
- ' --list list candidates instead of building or running them', &
- ' -- ARGS optional arguments to pass to the program(s). ', &
- ' The same arguments are passed to all names ', &
- ' specified. ', &
- ' ', &
- 'EXAMPLES ', &
- 'run fpm(1) project applications ', &
- ' ', &
- ' # run default programs in /app or as specified in "fpm.toml" ', &
- ' fpm run ', &
- ' ', &
- ' # run a specific program and pass arguments to the command ', &
- ' fpm run mytest -- -x 10 -y 20 -title "my title line" ', &
- ' ', &
- ' # production version of two applications ', &
- ' fpm run tst1 test2 -release ', &
- 'SEE ALSO ', &
- ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
- '' ]
- call set_args('--list F --release F --',help_text,version_text)
+ help_text=[character(len=80) :: &
+ 'NAME ', &
+ ' run(1) - the fpm(1) subcommand to run project applications ', &
+ ' ', &
+ 'SYNOPSIS ', &
+ ' fpm run [NAME(s)] [--release] [-- ARGS] ', &
+ ' ', &
+ ' fpm run --help|--version ', &
+ ' ', &
+ 'DESCRIPTION ', &
+ ' Run applications you have built in your fpm(1) project. ', &
+ ' ', &
+ 'OPTIONS ', &
+ ' NAME(s) optional list of specific names to execute. ', &
+ ' The default is to run all the applications in app/ ', &
+ ' or the programs listed in the "fpm.toml" file. ', &
+ ' --release selects the optimized build instead of the debug ', &
+ ' build. ', &
+ ' --list list candidates instead of building or running them', &
+ ' -- ARGS optional arguments to pass to the program(s). ', &
+ ' The same arguments are passed to all names ', &
+ ' specified. ', &
+ ' ', &
+ 'EXAMPLES ', &
+ 'run fpm(1) project applications ', &
+ ' ', &
+ ' # run default programs in /app or as specified in "fpm.toml" ', &
+ ' fpm run ', &
+ ' ', &
+ ' # run a specific program and pass arguments to the command ', &
+ ' fpm run mytest -- -x 10 -y 20 -title "my title line" ', &
+ ' ', &
+ ' # production version of two applications ', &
+ ' fpm run tst1 test2 -release ', &
+ 'SEE ALSO ', &
+ ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
+ '' ]
+ call set_args('--list F --release F --',help_text,version_text)
- if( size(unnamed) .gt. 1 )then
- names=unnamed(2:)
- else
- names=[character(len=len(names)) :: ]
- endif
+ if( size(unnamed) .gt. 1 )then
+ names=unnamed(2:)
+ else
+ names=[character(len=len(names)) :: ]
+ endif
- allocate(fpm_run_settings :: cmd_settings)
- cmd_settings=fpm_run_settings( name=names, list=lget('list'), &
- & release=lget('release'), args=remaining )
+ allocate(fpm_run_settings :: cmd_settings)
+ cmd_settings=fpm_run_settings( name=names, list=lget('list'), &
+ & release=lget('release'), args=remaining )
case('build')
- help_text=[character(len=80) :: &
- 'NAME ', &
- ' build(1) - the fpm(1) subcommand to build a project ', &
- 'SYNOPSIS ', &
- ' fpm build [--release]|[-list] ', &
- ' fpm build --help|--version ', &
- ' ', &
- 'DESCRIPTION ', &
- ' The "fpm build" command ', &
- ' o Fetches any dependencies ', &
- ' o Scans your sources ', &
- ' o Builds them in the proper order ', &
- ' ', &
- ' The Fortran source files are assumed to be in app/, test/, and src/ ', &
- ' by default. The changed or new files found are rebuilt. ', &
- ' The results are placed in the build/ directory. ', &
- ' ', &
- ' Non-default pathnames and remote dependencies are used if ', &
- ' specified in the "fpm.toml" file. ', &
- ' ', &
- 'OPTIONS ', &
- ' --release build in build/*_release instead of build/*_debug with ', &
- ' high optimization instead of full debug options. ', &
- ' --list list candidates instead of building or running them ', &
- ' --help print this help and exit ', &
- ' --version print program version information and exit ', &
- ' ', &
- 'EXAMPLES ', &
- ' Sample commands: ', &
- ' ', &
- ' fpm build # build with debug options ', &
- ' fpm build -release # build with high optimization ', &
- 'SEE ALSO ', &
- ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
- '' ]
- call set_args( '--release F --list F --',help_text,version_text )
+ help_text=[character(len=80) :: &
+ 'NAME ', &
+ ' build(1) - the fpm(1) subcommand to build a project ', &
+ 'SYNOPSIS ', &
+ ' fpm build [--release]|[-list] ', &
+ ' fpm build --help|--version ', &
+ ' ', &
+ 'DESCRIPTION ', &
+ ' The "fpm build" command ', &
+ ' o Fetches any dependencies ', &
+ ' o Scans your sources ', &
+ ' o Builds them in the proper order ', &
+ ' ', &
+ ' The Fortran source files are assumed to be in app/, test/, and src/ ', &
+ ' by default. The changed or new files found are rebuilt. ', &
+ ' The results are placed in the build/ directory. ', &
+ ' ', &
+ ' Non-default pathnames and remote dependencies are used if ', &
+ ' specified in the "fpm.toml" file. ', &
+ ' ', &
+ 'OPTIONS ', &
+ ' --release build in build/*_release instead of build/*_debug with ', &
+ ' high optimization instead of full debug options. ', &
+ ' --list list candidates instead of building or running them ', &
+ ' --help print this help and exit ', &
+ ' --version print program version information and exit ', &
+ ' ', &
+ 'EXAMPLES ', &
+ ' Sample commands: ', &
+ ' ', &
+ ' fpm build # build with debug options ', &
+ ' fpm build -release # build with high optimization ', &
+ 'SEE ALSO ', &
+ ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
+ '' ]
+ call set_args( '--release F --list F --',help_text,version_text )
- allocate( fpm_build_settings :: cmd_settings )
- cmd_settings=fpm_build_settings( release=lget('release'),list=lget('list') )
+ allocate( fpm_build_settings :: cmd_settings )
+ cmd_settings=fpm_build_settings( release=lget('release'),list=lget('list') )
case('new')
- help_text=[character(len=80) :: &
- 'NAME ', &
- ' new(1) - the fpm(1) subcommand to initialize a new project ', &
- 'SYNOPSIS ', &
- ' fpm new NAME [--with-executable] [--with-test] ', &
- ' ', &
- ' fpm new --help|--version ', &
- ' ', &
- 'DESCRIPTION ', &
- ' Create a new programming project in a new directory ', &
- ' ', &
- ' The "new" subcommand creates a directory and runs the command ', &
- ' "git init" in that directory and makes an example "fpm.toml" ', &
- ' file, a src/ directory, and optionally a test/ and app/ ', &
- ' directory with trivial example Fortran source files. ', &
- ' ', &
- ' Remember to update the information in the sample "fpm.toml" ', &
- ' file with such information as your name and e-mail address. ', &
- ' ', &
- ' OPTIONS ', &
- ' NAME the name of the project directory to create. The name ', &
- ' must be a valid Fortran name composed of 1 to 63 ', &
- ' ASCII alphanumeric characters and underscores, ', &
- ' starting with a letter. ', &
- ' --with-executable additionally create optional directory app/ ', &
- ' and placeholder program for "fpm run". ', &
- ' --with-test additionally create optional directory test/', &
- ' and placeholder program for "fpm test". ', &
- ' --help print this help and exit ', &
- ' --version print program version information and exit ', &
- ' ', &
- 'EXAMPLES ', &
- ' Sample use ', &
- ' ', &
- ' fpm new myproject # create new project directory and seed it', &
- ' cd myproject # Enter the new directory ', &
- ' # and run commands such as ', &
- ' fpm build ', &
- ' fpm run # if you selected --with-executable ', &
- ' fpm test # if you selected --with-test ', &
- 'SEE ALSO ', &
- ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
- ' ', &
- ' Registered packages are at https://fortran-lang.org/packages ', &
- '' ]
- call set_args(' --with-executable F --with-test F --lib F --app F --test F', help_text, version_text)
- select case(size(unnamed))
- case(1)
- write(stderr,'(*(g0))')'ERROR: directory name required'
- write(stderr,'(*(g0))')' usage: fpm new NAME [--with-executable] [--with-test]'
- stop 1
- case(2)
- name=trim(unnamed(2))
- case default
- write(stderr,'(*(g0))')'ERROR: only one directory name allowed'
- write(stderr,'(*(g0))')' usage: fpm new NAME [--with-executable] [--with-test]'
- stop 2
- end select
+ help_text=[character(len=80) :: &
+ 'NAME ', &
+ ' new(1) - the fpm(1) subcommand to initialize a new project ', &
+ 'SYNOPSIS ', &
+ ' fpm new NAME [--with-executable] [--with-test] ', &
+ ' ', &
+ ' fpm new --help|--version ', &
+ ' ', &
+ 'DESCRIPTION ', &
+ ' Create a new programming project in a new directory ', &
+ ' ', &
+ ' The "new" subcommand creates a directory and runs the command ', &
+ ' "git init" in that directory and makes an example "fpm.toml" ', &
+ ' file, a src/ directory, and optionally a test/ and app/ ', &
+ ' directory with trivial example Fortran source files. ', &
+ ' ', &
+ ' Remember to update the information in the sample "fpm.toml" ', &
+ ' file with such information as your name and e-mail address. ', &
+ ' ', &
+ ' OPTIONS ', &
+ ' NAME the name of the project directory to create. The name ', &
+ ' must be a valid Fortran name composed of 1 to 63 ', &
+ ' ASCII alphanumeric characters and underscores, ', &
+ ' starting with a letter. ', &
+ ' --with-executable additionally create optional directory app/ ', &
+ ' and placeholder program for "fpm run". ', &
+ ' --with-test additionally create optional directory test/', &
+ ' and placeholder program for "fpm test". ', &
+ ' --help print this help and exit ', &
+ ' --version print program version information and exit ', &
+ ' ', &
+ 'EXAMPLES ', &
+ ' Sample use ', &
+ ' ', &
+ ' fpm new myproject # create new project directory and seed it', &
+ ' cd myproject # Enter the new directory ', &
+ ' # and run commands such as ', &
+ ' fpm build ', &
+ ' fpm run # if you selected --with-executable ', &
+ ' fpm test # if you selected --with-test ', &
+ 'SEE ALSO ', &
+ ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
+ ' ', &
+ ' Registered packages are at https://fortran-lang.org/packages ', &
+ '' ]
+ call set_args(' --with-executable F --with-test F --lib F --app F --test F', help_text, version_text)
+ select case(size(unnamed))
+ case(1)
+ write(stderr,'(*(g0))')'ERROR: directory name required'
+ write(stderr,'(*(g0))')' usage: fpm new NAME [--with-executable] [--with-test]'
+ stop 1
+ case(2)
+ name=trim(unnamed(2))
+ case default
+ write(stderr,'(*(g0))')'ERROR: only one directory name allowed'
+ write(stderr,'(*(g0))')' usage: fpm new NAME [--with-executable] [--with-test]'
+ stop 2
+ end select
- if( .not.fortran_name(basename(name)) )then
- write(stderr,'(*(g0))')'ERROR: new directory name must be an allowed Fortran name.'
- write(stderr,'(*(g0))')' It must be composed of 1 to 63 ASCII characters and start'
- write(stderr,'(*(g0))')' with a letter and be composed entirely of alphanumeric'
- write(stderr,'(*(g0))')' characters [A-Za-z] and underscores.'
- stop 4
- endif
+ if( .not.fortran_name(basename(name)) )then
+ write(stderr,'(*(g0))')'ERROR: new directory name must be an allowed Fortran name.'
+ write(stderr,'(*(g0))')' It must be composed of 1 to 63 ASCII characters and start'
+ write(stderr,'(*(g0))')' with a letter and be composed entirely of alphanumeric'
+ write(stderr,'(*(g0))')' characters [A-Za-z] and underscores.'
+ stop 4
+ endif
- allocate(fpm_new_settings :: cmd_settings)
- cmd_settings=fpm_new_settings(name=name, &
- & with_executable=lget('with-executable'), &
- & with_test=lget('with-test'), &
- & with_lib=.true.)
+ allocate(fpm_new_settings :: cmd_settings)
+ cmd_settings=fpm_new_settings(name=name, &
+ & with_executable=lget('with-executable'), &
+ & with_test=lget('with-test'), &
+ & with_lib=.true.)
- ! use alternative --lib --test --app switches. In production pick one
- ! method or probably an error should be using --with and one of these
- if (any( specified(['lib ','app ','test']) ) )then
- if (any( specified(['with-executable','with-test ']) ) )then
- write(stderr,'(*(g0))') 'A BIT FROWARD:'
- write(stderr,'(*(g0))') ' DO NOT MIX --with-* with [--lib|--app|--test]'
- write(stderr,'(*(g0))') ' THEY ARE TWO DIFFERENT PROTOTYPE PROPOSALS '
- write(stderr,'(*(g0))') ' SEE ISSUES #111 #110 #109'
- write(stderr,'(*(g0))') ' START WITH https://github.com/fortran-lang/fpm/issues/111'
- endif
- cmd_settings=fpm_new_settings(name=name, &
- & with_executable=lget('app'), &
- & with_test=lget('test'), &
- & with_lib=lget('lib') )
- endif
+ ! use alternative --lib --test --app switches. In production pick one
+ ! method or probably an error should be using --with and one of these
+ if (any( specified(['lib ','app ','test']) ) )then
+ if (any( specified(['with-executable','with-test ']) ) )then
+ write(stderr,'(*(g0))') 'A BIT FROWARD:'
+ write(stderr,'(*(g0))') ' DO NOT MIX --with-* with [--lib|--app|--test]'
+ write(stderr,'(*(g0))') ' THEY ARE TWO DIFFERENT PROTOTYPE PROPOSALS '
+ write(stderr,'(*(g0))') ' SEE ISSUES #111 #110 #109'
+ write(stderr,'(*(g0))') ' START WITH https://github.com/fortran-lang/fpm/issues/111'
+ endif
+ cmd_settings=fpm_new_settings(name=name, &
+ & with_executable=lget('app'), &
+ & with_test=lget('test'), &
+ & with_lib=lget('lib') )
+ endif
case('install')
- help_text=[character(len=80) :: &
- ' fpm(1) subcommand "install" ', &
- ' ', &
- ' Usage: fpm install NAME ', &
- '' ]
- call set_args('--release F ', help_text, version_text)
+ help_text=[character(len=80) :: &
+ ' fpm(1) subcommand "install" ', &
+ ' ', &
+ ' Usage: fpm install NAME ', &
+ '' ]
+ call set_args('--release F ', help_text, version_text)
- allocate(fpm_install_settings :: cmd_settings)
+ allocate(fpm_install_settings :: cmd_settings)
case('test')
- help_text=[character(len=80) :: &
- 'NAME ', &
- ' test(1) - the fpm(1) subcommand to run project tests ', &
- ' ', &
- 'SYNOPSIS ', &
- ' fpm test [NAME(s)] [--release] [--list] [-- ARGS] ', &
- ' ', &
- ' fpm test --help|--version ', &
- ' ', &
- 'DESCRIPTION ', &
- ' Run applications you have built to test your project. ', &
- ' ', &
- 'OPTIONS ', &
- ' NAME(s) optional list of specific test names to execute. ', &
- ' The default is to run all the tests in test/ ', &
- ' or the tests listed in the "fpm.toml" file. ', &
- ' --release selects the optimized build instead of the debug ', &
- ' build. ', &
- ' --list list candidates instead of building or running them', &
- ' -- ARGS optional arguments to pass to the test program(s). ', &
- ' The same arguments are passed to all test names ', &
- ' specified. ', &
- ' ', &
- 'EXAMPLES ', &
- 'run tests ', &
- ' ', &
- ' # run default tests in /test or as specified in "fpm.toml" ', &
- ' fpm test ', &
- ' ', &
- ' # run a specific test and pass arguments to the command ', &
- ' fpm test mytest -- -x 10 -y 20 -title "my title line" ', &
- ' ', &
- ' fpm test tst1 test2 -release # production version of two tests', &
- 'SEE ALSO ', &
- ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
- '' ]
- call set_args('--list F --release F --',help_text,version_text)
+ help_text=[character(len=80) :: &
+ 'NAME ', &
+ ' test(1) - the fpm(1) subcommand to run project tests ', &
+ ' ', &
+ 'SYNOPSIS ', &
+ ' fpm test [NAME(s)] [--release] [--list] [-- ARGS] ', &
+ ' ', &
+ ' fpm test --help|--version ', &
+ ' ', &
+ 'DESCRIPTION ', &
+ ' Run applications you have built to test your project. ', &
+ ' ', &
+ 'OPTIONS ', &
+ ' NAME(s) optional list of specific test names to execute. ', &
+ ' The default is to run all the tests in test/ ', &
+ ' or the tests listed in the "fpm.toml" file. ', &
+ ' --release selects the optimized build instead of the debug ', &
+ ' build. ', &
+ ' --list list candidates instead of building or running them', &
+ ' -- ARGS optional arguments to pass to the test program(s). ', &
+ ' The same arguments are passed to all test names ', &
+ ' specified. ', &
+ ' ', &
+ 'EXAMPLES ', &
+ 'run tests ', &
+ ' ', &
+ ' # run default tests in /test or as specified in "fpm.toml" ', &
+ ' fpm test ', &
+ ' ', &
+ ' # run a specific test and pass arguments to the command ', &
+ ' fpm test mytest -- -x 10 -y 20 -title "my title line" ', &
+ ' ', &
+ ' fpm test tst1 test2 -release # production version of two tests', &
+ 'SEE ALSO ', &
+ ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
+ '' ]
+ call set_args('--list F --release F --',help_text,version_text)
- if( size(unnamed) .gt. 1 )then
- names=unnamed(2:)
- else
- names=[character(len=len(names)) :: ]
- endif
+ if( size(unnamed) .gt. 1 )then
+ names=unnamed(2:)
+ else
+ names=[character(len=len(names)) :: ]
+ endif
- allocate(fpm_test_settings :: cmd_settings)
- cmd_settings=fpm_test_settings( name=names, list=lget('list'), &
- & release=lget('release'), args=remaining )
+ allocate(fpm_test_settings :: cmd_settings)
+ cmd_settings=fpm_test_settings( name=names, list=lget('list'), &
+ & release=lget('release'), args=remaining )
case default
- help_text=[character(len=80) :: &
- 'NAME', &
- ' fpm(1) - A Fortran package manager and build system', &
- 'OS TYPE' ]
+ help_text=[character(len=80) :: &
+ 'NAME', &
+ ' fpm(1) - A Fortran package manager and build system', &
+ 'OS TYPE' ]
select case (get_os_type())
- case (OS_LINUX); help_text=[character(len=80) :: help_text, " Linux" ]
- case (OS_MACOS); help_text=[character(len=80) :: help_text, " macOS" ]
- case (OS_WINDOWS); help_text=[character(len=80) :: help_text, " Windows" ]
- case (OS_CYGWIN); help_text=[character(len=80) :: help_text, " Cygwin" ]
- case (OS_SOLARIS); help_text=[character(len=80) :: help_text, " Solaris" ]
- case (OS_FREEBSD); help_text=[character(len=80) :: help_text, " FreeBSD" ]
- case (OS_UNKNOWN); help_text=[character(len=80) :: help_text, " Unknown" ]
- case default ; help_text=[character(len=80) :: help_text, " UNKNOWN" ]
+ case (OS_LINUX); help_text=[character(len=80) :: help_text, " Linux" ]
+ case (OS_MACOS); help_text=[character(len=80) :: help_text, " macOS" ]
+ case (OS_WINDOWS); help_text=[character(len=80) :: help_text, " Windows" ]
+ case (OS_CYGWIN); help_text=[character(len=80) :: help_text, " Cygwin" ]
+ case (OS_SOLARIS); help_text=[character(len=80) :: help_text, " Solaris" ]
+ case (OS_FREEBSD); help_text=[character(len=80) :: help_text, " FreeBSD" ]
+ case (OS_UNKNOWN); help_text=[character(len=80) :: help_text, " Unknown" ]
+ case default ; help_text=[character(len=80) :: help_text, " UNKNOWN" ]
end select
- help_text=[character(len=80) :: help_text, &
- 'SYNOPSIS ', &
- ' fpm SUBCOMMAND [SUBCOMMAND_OPTIONS] ', &
- ' ', &
- ' fpm --help|--version ', &
- ' ', &
- 'DESCRIPTION ', &
- ' fpm is a package manager that helps you create Fortran projects that are ', &
- ' optionally dependent on multiple files and other fpm(1) packages. ', &
- ' ', &
- ' Most significantly fpm(1) lets you pull upon other fpm(1) packages in ', &
- ' distributed git(1) repositories as if the packages were a basic part ', &
- ' of your default programming environment, as well as letting you share ', &
- ' your projects with others in a similar manner. ', &
- ' ', &
- ' See the fpm(1) repository for a listing of such available projects. ', &
- ' ', &
- ' All output goes into the directory "build/". ', &
- ' ', &
- 'SUBCOMMANDS ', &
- ' Valid fpm subcommands are: ', &
- ' ', &
- ' build [--release] [--list] ', &
- ' Compile the packages into the "build/" directory. ', &
- ' new NAME [--with-executable] [--with-test] ', &
- ' Create a new Fortran package directory ', &
- ' with sample files ', &
- ' run [NAME(s)] [--release] [--list] [-- ARGS] ', &
- ' Run the local package binaries. defaults to all ', &
- ' binaries for that release. ', &
- ' test [NAME(s)] [--release] [--list] [-- ARGS] ', &
- ' Run the tests ', &
- 'SUBCOMMAND OPTIONS ', &
- ' --release Builds or runs in release mode (versus debug mode). fpm(1) ', &
- ' Defaults to using common compiler debug flags and building ', &
- ' in "build/gfortran_debug/". When this flag is present build ', &
- ' output goes into "build/gfortran_release/" and common ', &
- ' compiler optimization flags are used. ', &
- ' --list list candidates instead of building or running them ', &
- ' -- ARGS Arguments to pass to executables/tests ', &
- ' --help Show this help text and exit. Valid for all subcommands. ', &
- ' --version Show version information and exit. Valid for all subcommands.', &
- 'EXAMPLES ', &
- ' sample commands: ', &
- ' ', &
- ' fpm build ', &
- ' fpm test ', &
- ' fpm run ', &
- ' fpm new --help ', &
- ' fpm new mypackage --with-executable --with-test ', &
- ' fpm run myprogram --release -- -x 10 -y 20 --title "my title" ', &
- 'SEE ALSO ', &
- ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
- '']
+ help_text=[character(len=80) :: help_text, &
+ 'SYNOPSIS ', &
+ ' fpm SUBCOMMAND [SUBCOMMAND_OPTIONS] ', &
+ ' ', &
+ ' fpm --help|--version ', &
+ ' ', &
+ 'DESCRIPTION ', &
+ ' fpm is a package manager that helps you create Fortran projects that are ', &
+ ' optionally dependent on multiple files and other fpm(1) packages. ', &
+ ' ', &
+ ' Most significantly fpm(1) lets you pull upon other fpm(1) packages in ', &
+ ' distributed git(1) repositories as if the packages were a basic part ', &
+ ' of your default programming environment, as well as letting you share ', &
+ ' your projects with others in a similar manner. ', &
+ ' ', &
+ ' See the fpm(1) repository for a listing of such available projects. ', &
+ ' ', &
+ ' All output goes into the directory "build/". ', &
+ ' ', &
+ 'SUBCOMMANDS ', &
+ ' Valid fpm subcommands are: ', &
+ ' ', &
+ ' build [--release] [--list] ', &
+ ' Compile the packages into the "build/" directory. ', &
+ ' new NAME [--with-executable] [--with-test] ', &
+ ' Create a new Fortran package directory ', &
+ ' with sample files ', &
+ ' run [NAME(s)] [--release] [--list] [-- ARGS] ', &
+ ' Run the local package binaries. defaults to all ', &
+ ' binaries for that release. ', &
+ ' test [NAME(s)] [--release] [--list] [-- ARGS] ', &
+ ' Run the tests ', &
+ 'SUBCOMMAND OPTIONS ', &
+ ' --release Builds or runs in release mode (versus debug mode). fpm(1) ', &
+ ' Defaults to using common compiler debug flags and building ', &
+ ' in "build/gfortran_debug/". When this flag is present build ', &
+ ' output goes into "build/gfortran_release/" and common ', &
+ ' compiler optimization flags are used. ', &
+ ' --list list candidates instead of building or running them ', &
+ ' -- ARGS Arguments to pass to executables/tests ', &
+ ' --help Show this help text and exit. Valid for all subcommands. ', &
+ ' --version Show version information and exit. Valid for all subcommands.', &
+ 'EXAMPLES ', &
+ ' sample commands: ', &
+ ' ', &
+ ' fpm build ', &
+ ' fpm test ', &
+ ' fpm run ', &
+ ' fpm new --help ', &
+ ' fpm new mypackage --with-executable --with-test ', &
+ ' fpm run myprogram --release -- -x 10 -y 20 --title "my title" ', &
+ 'SEE ALSO ', &
+ ' The fpm(1) home page is https://github.com/fortran-lang/fpm ', &
+ '']
- call set_args(' ', help_text, version_text)
- ! Note: will not get here if --version or --usage or --help is present on commandline
- if(len_trim(cmdarg).eq.0)then
- write(stderr,'(*(a))')'ERROR: missing subcommand'
- else
- write(stderr,'(*(a))')'ERROR: unknown subcommand [', trim(cmdarg), ']'
- endif
- help_text=[character(len=80) :: &
- 'USAGE: fpm [ SUBCOMMAND [SUBCOMMAND_OPTIONS] ] | [|--help|--version] ', &
- ' Enter "fpm --help" for more information ', &
- '' ]
- write(stderr,'(g0)')(trim(help_text(i)), i=1, size(help_text) )
- !!stop 3 ! causes github site tests to fail
- stop
+ call set_args(' ', help_text, version_text)
+ ! Note: will not get here if --version or --usage or --help is present on commandline
+ if(len_trim(cmdarg).eq.0)then
+ write(stderr,'(*(a))')'ERROR: missing subcommand'
+ else
+ write(stderr,'(*(a))')'ERROR: unknown subcommand [', trim(cmdarg), ']'
+ endif
+ help_text=[character(len=80) :: &
+ 'USAGE: fpm [ SUBCOMMAND [SUBCOMMAND_OPTIONS] ] | [|--help|--version] ', &
+ ' Enter "fpm --help" for more information ', &
+ '' ]
+ write(stderr,'(g0)')(trim(help_text(i)), i=1, size(help_text) )
+ !!stop 3 ! causes github site tests to fail
+ stop
end select
- end subroutine get_command_line_settings
+ end subroutine get_command_line_settings
- function fortran_name(line) result (lout)
- ! determine if a string is a valid Fortran name ignoring trailing spaces (but not leading spaces)
- character(len=*),parameter :: int='0123456789'
- character(len=*),parameter :: lower='abcdefghijklmnopqrstuvwxyz'
- character(len=*),parameter :: upper='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- character(len=*),parameter :: allowed=upper//lower//int//'_'
- character(len=*),intent(in) :: line
- character(len=:),allocatable :: name
- logical :: lout
- name=trim(line)
- if(len(name).ne.0)then
- lout = .true. &
- & .and. verify(name(1:1), lower//upper) == 0 &
- & .and. verify(name,allowed) == 0 &
- & .and. len(name) <= 63
- else
- lout = .false.
- endif
- end function fortran_name
+ function fortran_name(line) result (lout)
+ ! determine if a string is a valid Fortran name ignoring trailing spaces (but not leading spaces)
+ character(len=*),parameter :: int='0123456789'
+ character(len=*),parameter :: lower='abcdefghijklmnopqrstuvwxyz'
+ character(len=*),parameter :: upper='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ character(len=*),parameter :: allowed=upper//lower//int//'_'
+ character(len=*),intent(in) :: line
+ character(len=:),allocatable :: name
+ logical :: lout
+ name=trim(line)
+ if(len(name).ne.0)then
+ lout = .true. &
+ & .and. verify(name(1:1), lower//upper) == 0 &
+ & .and. verify(name,allowed) == 0 &
+ & .and. len(name) <= 63
+ else
+ lout = .false.
+ endif
+ end function fortran_name
end module fpm_command_line