From 9bc3b786c1a0b56c5037e1cf391b9f0cb5a065e9 Mon Sep 17 00:00:00 2001 From: Sebastian Ehlert <28669218+awvwgk@users.noreply.github.com> Date: Sat, 28 Aug 2021 13:53:30 +0200 Subject: [PATCH 1/4] Use environment variables for Fortran compiler and arguments - Read Fortran compiler from FC (overwritten by FPM_COMPILER for compatibility) - Read Fortran compiler options from FFLAGS - Read C compiler from CC (remove FPM_C_COMPILER since it was never documented) - Read archiver from AR --- src/fpm_command_line.f90 | 123 ++++++++++++++++++++++----------------- src/fpm_compiler.f90 | 13 +++-- 2 files changed, 77 insertions(+), 59 deletions(-) diff --git a/src/fpm_command_line.f90 b/src/fpm_command_line.f90 index 2f00b5865b..e83bd8e417 100644 --- a/src/fpm_command_line.f90 +++ b/src/fpm_command_line.f90 @@ -121,7 +121,7 @@ subroutine get_command_line_settings(cmd_settings) integer :: i integer :: widest type(fpm_install_settings), allocatable :: install_settings - character(len=:), allocatable :: common_args, working_dir + character(len=:), allocatable :: common_args, compiler_args, run_args, working_dir call set_help() ! text for --version switch, @@ -148,23 +148,28 @@ subroutine get_command_line_settings(cmd_settings) CLI_RESPONSE_FILE=.true. cmdarg = get_subcommand() - common_args = '--directory:C " " ' + common_args = & + ' --directory:C " "' // & + ' --verbose F' + + run_args = & + ' --target " "' // & + ' --list F' // & + ' --runner " "' + + compiler_args = & + ' --profile " "' // & + ' --compiler "'//get_fc_env()//'"' // & + ' --flag:: "'//get_fflags_env()//'"' ! now set subcommand-specific help text and process commandline ! arguments. Then call subcommand routine select case(trim(cmdarg)) case('run') - call set_args(common_args //'& - & --target " " & - & --list F & + call set_args(common_args // compiler_args // run_args //'& & --all F & - & --profile " "& & --example F& - & --runner " " & - & --compiler "'//get_env('FPM_COMPILER','gfortran')//'" & - & --flag:: " "& - & --verbose F& & --',help_run,version_text) call check_build_vals() @@ -207,13 +212,9 @@ subroutine get_command_line_settings(cmd_settings) & verbose=lget('verbose') ) case('build') - call set_args(common_args // '& - & --profile " " & + call set_args(common_args // compiler_args //'& & --list F & & --show-model F & - & --compiler "'//get_env('FPM_COMPILER','gfortran')//'" & - & --flag:: " "& - & --verbose F& & --',help_build,version_text) call check_build_vals() @@ -236,8 +237,7 @@ subroutine get_command_line_settings(cmd_settings) & --example F & & --backfill F & & --full F & - & --bare F & - & --verbose:V F',& + & --bare F', & & help_new, version_text) select case(size(unnamed)) case(1) @@ -296,9 +296,7 @@ subroutine get_command_line_settings(cmd_settings) endif case('help','manual') - call set_args(common_args // '& - & --verbose F & - & ',help_help,version_text) + call set_args(common_args, help_help,version_text) if(size(unnamed).lt.2)then if(unnamed(1).eq.'help')then unnamed=[' ', 'fpm'] @@ -344,11 +342,9 @@ subroutine get_command_line_settings(cmd_settings) call printhelp(help_text) case('install') - call set_args(common_args // '& - & --profile " " --no-rebuild F --verbose F --prefix " " & + call set_args(common_args // compiler_args // '& + & --no-rebuild F --prefix " " & & --list F & - & --compiler "'//get_env('FPM_COMPILER','gfortran')//'" & - & --flag:: " "& & --libdir "lib" --bindir "bin" --includedir "include"', & help_install, version_text) @@ -371,22 +367,14 @@ subroutine get_command_line_settings(cmd_settings) case('list') call set_args(common_args // '& & --list F& - & --verbose F& &', help_list, version_text) call printhelp(help_list_nodash) if(lget('list'))then call printhelp(help_list_dash) endif case('test') - call set_args(common_args // '& - & --target " " & - & --list F& - & --profile " "& - & --runner " " & - & --compiler "'//get_env('FPM_COMPILER','gfortran')//'" & - & --flag:: " "& - & --verbose F& - & --',help_test,version_text) + call set_args(common_args // compiler_args // run_args // ' --', & + help_test,version_text) call check_build_vals() @@ -422,7 +410,7 @@ subroutine get_command_line_settings(cmd_settings) & verbose=lget('verbose') ) case('update') - call set_args(common_args // ' --fetch-only F --verbose F --clean F', & + call set_args(common_args // ' --fetch-only F --clean F', & help_update, version_text) if( size(unnamed) .gt. 1 )then @@ -443,7 +431,6 @@ subroutine get_command_line_settings(cmd_settings) else call set_args('& & --list F& - & --verbose F& &', help_fpm, version_text) ! Note: will not get here if --version or --usage or --help ! is present on commandline @@ -658,16 +645,17 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build. These are',& - ' added to the profile options if --profile is specified,',& - ' else these options override the defaults.',& + ' --flag FFLAGS selects compile arguments for the build, the default',& + ' value is set by the FFLAGS environment variable.', & + ' These are added to the profile options if --profile', & + ' is specified, else these options override the defaults.',& ' Note object and .mod directory locations are always',& ' built in.',& ' --list List candidates instead of building or running them. On ', & ' the fpm(1) command this shows a brief list of subcommands.', & ' --runner CMD Provides a command to prefix program execution paths. ', & ' --compiler COMPILER_NAME Compiler name. The environment variable ', & - ' FPM_COMPILER sets the default. ', & + ' FC sets the default. ', & ' -- ARGS Arguments to pass to executables. ', & ' ', & 'VALID FOR ALL SUBCOMMANDS ', & @@ -783,14 +771,15 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build. These are',& - ' added to the profile options if --profile is specified,',& - ' else these options override the defaults.',& + ' --flag FFLAGS selects compile arguments for the build, the default',& + ' value is set by the FFLAGS environment variable.', & + ' These are added to the profile options if --profile', & + ' is specified, else these options override the defaults.',& ' Note object and .mod directory locations are always',& ' built in.',& ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & ' "gfortran" unless set by the environment ', & - ' variable FPM_COMPILER. ', & + ' variable FC. ', & ' --runner CMD A command to prefix the program execution paths with. ', & ' see "fpm help runner" for further details. ', & ' --list list pathname of candidates instead of running them. Note ', & @@ -855,14 +844,15 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build. These are',& - ' added to the profile options if --profile is specified,',& - ' else these options override the defaults.',& + ' --flag FFLAGS selects compile arguments for the build, the default',& + ' value is set by the FFLAGS environment variable.', & + ' These are added to the profile options if --profile', & + ' is specified, else these options override the defaults.',& ' Note object and .mod directory locations are always',& ' built in.',& ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & ' "gfortran" unless set by the environment ', & - ' variable FPM_COMPILER. ', & + ' variable FC. ', & ' --list list candidates instead of building or running them ', & ' --show-model show the model and exit (do not build) ', & ' --help print this help and exit ', & @@ -1035,14 +1025,15 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build. These are',& - ' added to the profile options if --profile is specified,',& - ' else these options override the defaults.',& + ' --flag FFLAGS selects compile arguments for the build, the default',& + ' value is set by the FFLAGS environment variable.', & + ' These are added to the profile options if --profile', & + ' is specified, else these options override the defaults.',& ' Note object and .mod directory locations are always',& ' built in.',& ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & ' "gfortran" unless set by the environment ', & - ' variable FPM_COMPILER. ', & + ' variable FC. ', & ' --runner CMD A command to prefix the program execution paths with. ', & ' see "fpm help runner" for further details. ', & ' --list list candidates instead of building or running them ', & @@ -1107,9 +1098,10 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build. These are',& - ' added to the profile options if --profile is specified,',& - ' else these options override the defaults.',& + ' --flag FFLAGS selects compile arguments for the build, the default',& + ' value is set by the FFLAGS environment variable.', & + ' These are added to the profile options if --profile', & + ' is specified, else these options override the defaults.',& ' Note object and .mod directory locations are always',& ' built in.',& ' --no-rebuild do not rebuild project before installation', & @@ -1145,4 +1137,25 @@ subroutine get_char_arg(var, arg) if (len_trim(var) == 0) deallocate(var) end subroutine get_char_arg + + !> Get Fortran compiler from environment. + function get_fc_env() result(fc) + character(len=:), allocatable :: fc + + character(len=*), parameter :: fc_env = "FC", fc_env_long = "FPM_COMPILER" + character(len=*), parameter :: fc_default = "gfortran" + + fc = get_env(fc_env_long, get_env(fc_env, fc_default)) + end function get_fc_env + + !> Get Fortran compiler arguments from environment. + function get_fflags_env() result(fflags) + character(len=:), allocatable :: fflags + + character(len=*), parameter :: fflags_env = "FFLAGS" + character(len=*), parameter :: fflags_default = " " + + fflags = get_env(fflags_env, fflags_default) + end function get_fflags_env + end module fpm_command_line diff --git a/src/fpm_compiler.f90 b/src/fpm_compiler.f90 index c8858b79ff..1969f8d478 100644 --- a/src/fpm_compiler.f90 +++ b/src/fpm_compiler.f90 @@ -602,7 +602,7 @@ subroutine new_compiler(self, fc) !> New instance of the compiler type(compiler_t), intent(out) :: self - character(len=*), parameter :: cc_env = "FPM_C_COMPILER" + character(len=*), parameter :: cc_env = "CC" self%id = get_compiler_id(fc) @@ -618,16 +618,21 @@ subroutine new_archiver(self) type(archiver_t), intent(out) :: self integer :: estat, os_type + character(len=:), allocatable :: ar + character(len=*), parameter :: arflags = " -rs " + + ar = get_env("AR", "ar") + os_type = get_os_type() if (os_type /= OS_WINDOWS .and. os_type /= OS_UNKNOWN) then - self%ar = "ar -rs " + self%ar = ar//arflags else - call execute_command_line("ar --version > "//get_temp_filename()//" 2>&1", & + call execute_command_line(ar//" --version > "//get_temp_filename()//" 2>&1", & & exitstat=estat) if (estat /= 0) then self%ar = "lib /OUT:" else - self%ar = "ar -rs " + self%ar = ar//arflags end if end if self%use_response_file = os_type == OS_WINDOWS From ec88660c8ad14bea3908b054fd549934c268f954 Mon Sep 17 00:00:00 2001 From: Sebastian Ehlert <28669218+awvwgk@users.noreply.github.com> Date: Sun, 29 Aug 2021 07:46:16 +0200 Subject: [PATCH 2/4] Allow usage of --c-flag / CFLAGS and --link-flag / LDFLAGS --- src/fpm.f90 | 9 +++- src/fpm_command_line.f90 | 114 ++++++++++++++++++++++++--------------- src/fpm_model.f90 | 8 +++ src/fpm_targets.f90 | 4 +- 4 files changed, 89 insertions(+), 46 deletions(-) diff --git a/src/fpm.f90 b/src/fpm.f90 index 7208abf9d6..6d25fce30c 100644 --- a/src/fpm.f90 +++ b/src/fpm.f90 @@ -39,7 +39,7 @@ subroutine build_model(model, settings, package, error) integer :: i, j type(package_config_t) :: dependency - character(len=:), allocatable :: manifest, lib_dir, flags + character(len=:), allocatable :: manifest, lib_dir, flags, cflags, ldflags logical :: duplicates_found = .false. type(string_t) :: include_dir @@ -73,7 +73,10 @@ subroutine build_model(model, settings, package, error) end select end if - write(build_name, '(z16.16)') fnv_1a(flags) + cflags = trim(settings%cflag) + ldflags = trim(settings%ldflag) + + write(build_name, '(z16.16)') fnv_1a(flags//cflags//ldflags) if (model%compiler%is_unknown()) then write(*, '(*(a:,1x))') & @@ -195,6 +198,8 @@ subroutine build_model(model, settings, package, error) write(*,*)' COMPILER: ',model%compiler%fc write(*,*)' C COMPILER: ',model%compiler%cc write(*,*)' COMPILER OPTIONS: ', model%fortran_compile_flags + write(*,*)' C COMPILER OPTIONS: ', model%c_compile_flags + write(*,*)' LINKER OPTIONS: ', model%link_flags write(*,*)' INCLUDE DIRECTORIES: [', string_cat(model%include_dirs,','),']' end if diff --git a/src/fpm_command_line.f90 b/src/fpm_command_line.f90 index e83bd8e417..daac204be5 100644 --- a/src/fpm_command_line.f90 +++ b/src/fpm_command_line.f90 @@ -70,6 +70,8 @@ module fpm_command_line character(len=:),allocatable :: compiler character(len=:),allocatable :: profile character(len=:),allocatable :: flag + character(len=:),allocatable :: cflag + character(len=:),allocatable :: ldflag end type type, extends(fpm_build_settings) :: fpm_run_settings @@ -111,7 +113,45 @@ module fpm_command_line & ' ', 'fpm', 'new', 'build', 'run', & & 'test', 'runner', 'install', 'update', 'list', 'help', 'version' ] -character(len=:), allocatable :: val_runner, val_compiler, val_flag, val_profile +character(len=:), allocatable :: val_runner, val_compiler, val_flag, val_cflag, val_ldflag, & + val_profile + +character(len=80), parameter :: help_text_flag(*) = [character(len=80) :: & + ' --flag FFLAGS selects compile arguments for the build, the default',& + ' value is set by the FFLAGS environment variable.', & + ' These are added to the profile options if --profile', & + ' is specified, else these options override the defaults.',& + ' Note object and .mod directory locations are always',& + ' built in.',& + ' --c-flag CFLAGS selects compile arguments specific for C source in the build.',& + ' The default value is set by the CFLAGS environment variable.',& + ' --link-flag LDFLAGS',& + ' select arguments passed to the linker for the build.',& + ' The default value is set by the LDFLAGS environment variable.'& + ] + + +character(len=80), parameter :: help_text_environment(*) = [character(len=80) :: & + 'ENVIRONMENT VARIABLES',& + ' FPM_COMPILER sets the path to the Fortran compiler used for the build,', & + ' will be overwritten by --compiler command line option', & + '', & + ' FC sets the path to the Fortran compiler used for the build,', & + ' will be overwritten by FPM_COMPILER environment variable', & + '', & + ' FFLAGS sets the arguments for the Fortran compiler', & + ' will be overwritten by --flag command line option', & + '', & + ' CC sets the path to the C compiler used for the build,', & + '', & + ' CFLAGS sets the arguments for the C compiler', & + ' will be overwritten by --c-flag command line option', & + '', & + ' AR sets the path to the archiver used for the build,', & + '', & + ' LDFLAGS sets additional link arguments for creating executables', & + ' will be overwritten by --link-flag command line option' & + ] contains subroutine get_command_line_settings(cmd_settings) @@ -123,6 +163,9 @@ subroutine get_command_line_settings(cmd_settings) type(fpm_install_settings), allocatable :: install_settings character(len=:), allocatable :: common_args, compiler_args, run_args, working_dir + character(len=*), parameter :: fflags_env = "FFLAGS", cflags_env = "CFLAGS", & + & ldflags_env = "LDFLAGS", flags_default = " " + call set_help() ! text for --version switch, select case (get_os_type()) @@ -160,7 +203,9 @@ subroutine get_command_line_settings(cmd_settings) compiler_args = & ' --profile " "' // & ' --compiler "'//get_fc_env()//'"' // & - ' --flag:: "'//get_fflags_env()//'"' + ' --flag:: "'//get_env(fflags_env, flags_default)//'"' // & + ' --c-flag:: "'//get_env(cflags_env, flags_default)//'"' // & + ' --link-flag:: "'//get_env(ldflags_env, flags_default)//'"' ! now set subcommand-specific help text and process commandline ! arguments. Then call subcommand routine @@ -205,6 +250,8 @@ subroutine get_command_line_settings(cmd_settings) & profile=val_profile,& & compiler=val_compiler, & & flag=val_flag, & + & cflag=val_cflag, & + & ldflag=val_ldflag, & & example=lget('example'), & & list=lget('list'),& & name=names,& @@ -224,6 +271,8 @@ subroutine get_command_line_settings(cmd_settings) & profile=val_profile,& & compiler=val_compiler, & & flag=val_flag, & + & cflag=val_cflag, & + & ldflag=val_ldflag, & & list=lget('list'),& & show_model=lget('show-model'),& & verbose=lget('verbose') ) @@ -356,6 +405,8 @@ subroutine get_command_line_settings(cmd_settings) profile=val_profile,& compiler=val_compiler, & flag=val_flag, & + cflag=val_cflag, & + ldflag=val_ldflag, & no_rebuild=lget('no-rebuild'), & verbose=lget('verbose')) call get_char_arg(install_settings%prefix, 'prefix') @@ -403,6 +454,8 @@ subroutine get_command_line_settings(cmd_settings) & profile=val_profile, & & compiler=val_compiler, & & flag=val_flag, & + & cflag=val_cflag, & + & ldflag=val_ldflag, & & example=.false., & & list=lget('list'), & & name=names, & @@ -467,6 +520,8 @@ subroutine check_build_vals() endif val_flag = " " // sget('flag') + val_cflag = " " // sget('c-flag') + val_ldflag = " " // sget('link-flag') val_profile = sget('profile') end subroutine check_build_vals @@ -645,12 +700,7 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build, the default',& - ' value is set by the FFLAGS environment variable.', & - ' These are added to the profile options if --profile', & - ' is specified, else these options override the defaults.',& - ' Note object and .mod directory locations are always',& - ' built in.',& + help_text_flag, & ' --list List candidates instead of building or running them. On ', & ' the fpm(1) command this shows a brief list of subcommands.', & ' --runner CMD Provides a command to prefix program execution paths. ', & @@ -694,6 +744,8 @@ subroutine set_help() ' (currently) allow for continued lines or multiple specifications of ', & ' the same option. ', & ' ', & + help_text_environment, & + ' ', & 'EXAMPLES ', & ' sample commands: ', & ' ', & @@ -771,12 +823,7 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build, the default',& - ' value is set by the FFLAGS environment variable.', & - ' These are added to the profile options if --profile', & - ' is specified, else these options override the defaults.',& - ' Note object and .mod directory locations are always',& - ' built in.',& + help_text_flag, & ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & ' "gfortran" unless set by the environment ', & ' variable FC. ', & @@ -788,6 +835,8 @@ subroutine set_help() ' -- ARGS optional arguments to pass to the program(s). The same ', & ' arguments are passed to all program names specified. ', & ' ', & + help_text_environment, & + ' ', & 'EXAMPLES ', & ' fpm(1) - run or display project applications: ', & ' ', & @@ -844,12 +893,7 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build, the default',& - ' value is set by the FFLAGS environment variable.', & - ' These are added to the profile options if --profile', & - ' is specified, else these options override the defaults.',& - ' Note object and .mod directory locations are always',& - ' built in.',& + help_text_flag, & ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & ' "gfortran" unless set by the environment ', & ' variable FC. ', & @@ -858,6 +902,8 @@ subroutine set_help() ' --help print this help and exit ', & ' --version print program version information and exit ', & ' ', & + help_text_environment, & + ' ', & 'EXAMPLES ', & ' Sample commands: ', & ' ', & @@ -1025,12 +1071,7 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build, the default',& - ' value is set by the FFLAGS environment variable.', & - ' These are added to the profile options if --profile', & - ' is specified, else these options override the defaults.',& - ' Note object and .mod directory locations are always',& - ' built in.',& + help_text_flag, & ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & ' "gfortran" unless set by the environment ', & ' variable FC. ', & @@ -1041,6 +1082,8 @@ subroutine set_help() ' The same arguments are passed to all test names ', & ' specified. ', & ' ', & + help_text_environment, & + ' ', & 'EXAMPLES ', & 'run tests ', & ' ', & @@ -1098,12 +1141,7 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& - ' --flag FFLAGS selects compile arguments for the build, the default',& - ' value is set by the FFLAGS environment variable.', & - ' These are added to the profile options if --profile', & - ' is specified, else these options override the defaults.',& - ' Note object and .mod directory locations are always',& - ' built in.',& + help_text_flag, & ' --no-rebuild do not rebuild project before installation', & ' --prefix DIR path to installation directory (requires write access),', & ' the default prefix on Unix systems is $HOME/.local', & @@ -1115,6 +1153,8 @@ subroutine set_help() ' (default: include)', & ' --verbose print more information', & '', & + help_text_environment, & + '', & 'EXAMPLES', & ' 1. Install release version of project:', & '', & @@ -1148,14 +1188,4 @@ function get_fc_env() result(fc) fc = get_env(fc_env_long, get_env(fc_env, fc_default)) end function get_fc_env - !> Get Fortran compiler arguments from environment. - function get_fflags_env() result(fflags) - character(len=:), allocatable :: fflags - - character(len=*), parameter :: fflags_env = "FFLAGS" - character(len=*), parameter :: fflags_default = " " - - fflags = get_env(fflags_env, fflags_default) - end function get_fflags_env - end module fpm_command_line diff --git a/src/fpm_model.f90 b/src/fpm_model.f90 index 2dd9514d7a..c853b6f19d 100644 --- a/src/fpm_model.f90 +++ b/src/fpm_model.f90 @@ -124,6 +124,12 @@ module fpm_model !> Command line flags passed to fortran for compilation character(:), allocatable :: fortran_compile_flags + !> Command line flags passed to C for compilation + character(:), allocatable :: c_compile_flags + + !> Command line flags passed to the linker + character(:), allocatable :: link_flags + !> Base directory for build character(:), allocatable :: output_directory @@ -273,6 +279,8 @@ function info_model(model) result(s) s = s // ', archiver=(' // debug(model%archiver) // ')' ! character(:), allocatable :: fortran_compile_flags s = s // ', fortran_compile_flags="' // model%fortran_compile_flags // '"' + s = s // ', c_compile_flags="' // model%c_compile_flags // '"' + s = s // ', link_flags="' // model%link_flags // '"' ! character(:), allocatable :: output_directory s = s // ', output_directory="' // model%output_directory // '"' ! type(string_t), allocatable :: link_libraries(:) diff --git a/src/fpm_targets.f90 b/src/fpm_targets.f90 index d480866847..43001099a8 100644 --- a/src/fpm_targets.f90 +++ b/src/fpm_targets.f90 @@ -479,7 +479,7 @@ subroutine resolve_target_linking(targets, model) if (target%target_type /= FPM_TARGET_C_OBJECT) then target%compile_flags = model%fortran_compile_flags//" "//global_include_flags else - target%compile_flags = global_include_flags + target%compile_flags = model%c_compile_flags//" "//global_include_flags end if allocate(target%link_objects(0)) @@ -494,7 +494,7 @@ subroutine resolve_target_linking(targets, model) call get_link_objects(target%link_objects,target,is_exe=.true.) - target%link_flags = string_cat(target%link_objects," ") + target%link_flags = model%link_flags//" "//string_cat(target%link_objects," ") if (allocated(target%link_libraries)) then if (size(target%link_libraries) > 0) then From b7f873600523575423c769d9dfe6af138d9e7336 Mon Sep 17 00:00:00 2001 From: Sebastian Ehlert <28669218+awvwgk@users.noreply.github.com> Date: Mon, 30 Aug 2021 15:12:55 +0200 Subject: [PATCH 3/4] Use both plain and FPM_ prefixed variables - allow to set archiver and C compiler from command line --- src/fpm.f90 | 4 +- src/fpm_command_line.f90 | 101 ++++++++++++++++++++++++++------------- src/fpm_compiler.f90 | 54 ++++++++++++++------- 3 files changed, 105 insertions(+), 54 deletions(-) diff --git a/src/fpm.f90 b/src/fpm.f90 index 6d25fce30c..8d8b313ff4 100644 --- a/src/fpm.f90 +++ b/src/fpm.f90 @@ -60,8 +60,8 @@ subroutine build_model(model, settings, package, error) call filewrite(join_path("build", ".gitignore"),["*"]) end if - call new_compiler(model%compiler, settings%compiler) - call new_archiver(model%archiver) + call new_compiler(model%compiler, settings%compiler, settings%c_compiler) + call new_archiver(model%archiver, settings%archiver) if (settings%flag == '') then flags = model%compiler%get_default_flags(settings%profile == "release") diff --git a/src/fpm_command_line.f90 b/src/fpm_command_line.f90 index daac204be5..13624462a3 100644 --- a/src/fpm_command_line.f90 +++ b/src/fpm_command_line.f90 @@ -68,6 +68,8 @@ module fpm_command_line logical :: list=.false. logical :: show_model=.false. character(len=:),allocatable :: compiler + character(len=:),allocatable :: c_compiler + character(len=:),allocatable :: archiver character(len=:),allocatable :: profile character(len=:),allocatable :: flag character(len=:),allocatable :: cflag @@ -116,6 +118,15 @@ module fpm_command_line character(len=:), allocatable :: val_runner, val_compiler, val_flag, val_cflag, val_ldflag, & val_profile +character(len=80), parameter :: help_text_compiler(*) = [character(len=80) :: & + ' --compiler NAME Specify a compiler name. The default is "gfortran"',& + ' unless set by the environment variable FPM_FC or FC.',& + ' --c-compiler NAME Specify the C compiler name. By default automatic determined',& + ' unless set by the environment variable FPM_CC or CC.',& + ' --archiver NAME Specify the archiver name. By default automatic determined',& + ' unless set by the environment variable FPM_AR or AR.'& + ] + character(len=80), parameter :: help_text_flag(*) = [character(len=80) :: & ' --flag FFLAGS selects compile arguments for the build, the default',& ' value is set by the FFLAGS environment variable.', & @@ -133,23 +144,31 @@ module fpm_command_line character(len=80), parameter :: help_text_environment(*) = [character(len=80) :: & 'ENVIRONMENT VARIABLES',& - ' FPM_COMPILER sets the path to the Fortran compiler used for the build,', & + ' FPM_FC, FC sets the path to the Fortran compiler used for the build,', & + ' FPM_FC will take preference over FC, if both are set,', & ' will be overwritten by --compiler command line option', & '', & - ' FC sets the path to the Fortran compiler used for the build,', & - ' will be overwritten by FPM_COMPILER environment variable', & - '', & - ' FFLAGS sets the arguments for the Fortran compiler', & + ' FPM_FFLAGS, FFLAGS',& + ' sets the arguments for the Fortran compiler', & + ' FPM_FFLAGS will take preference over FFLAGS, if both are set,', & ' will be overwritten by --flag command line option', & '', & - ' CC sets the path to the C compiler used for the build,', & + ' FPM_CC, CC sets the path to the C compiler used for the build,', & + ' FPM_CC will take preference over CC, if both are set,', & + ' will be overwritten by --c-compiler command line option', & '', & - ' CFLAGS sets the arguments for the C compiler', & + ' FPM_CFLAGS, CFLAGS',& + ' sets the arguments for the C compiler', & + ' FPM_CFLAGS will take preference over CFLAGS, if both are set,', & ' will be overwritten by --c-flag command line option', & '', & - ' AR sets the path to the archiver used for the build,', & + ' FPM_AR, AR sets the path to the archiver used for the build,', & + ' FPM_AR will take preference over AR, if both are set,', & + ' will be overwritten by --archiver command line option', & '', & - ' LDFLAGS sets additional link arguments for creating executables', & + ' FPM_LDFLAGS, LDFLAGS',& + ' sets additional link arguments for creating executables', & + ' FPM_LDFLAGS will take preference over LDFLAGS, if both are set,', & ' will be overwritten by --link-flag command line option' & ] @@ -161,10 +180,12 @@ subroutine get_command_line_settings(cmd_settings) integer :: i integer :: widest type(fpm_install_settings), allocatable :: install_settings - character(len=:), allocatable :: common_args, compiler_args, run_args, working_dir + character(len=:), allocatable :: common_args, compiler_args, run_args, working_dir, & + & c_compiler, archiver - character(len=*), parameter :: fflags_env = "FFLAGS", cflags_env = "CFLAGS", & - & ldflags_env = "LDFLAGS", flags_default = " " + character(len=*), parameter :: fc_env = "FC", cc_env = "CC", ar_env = "AR", & + & fflags_env = "FFLAGS", cflags_env = "CFLAGS", ldflags_env = "LDFLAGS", & + & fc_default = "gfortran", cc_default = " ", ar_default = " ", flags_default = " " call set_help() ! text for --version switch, @@ -202,10 +223,12 @@ subroutine get_command_line_settings(cmd_settings) compiler_args = & ' --profile " "' // & - ' --compiler "'//get_fc_env()//'"' // & - ' --flag:: "'//get_env(fflags_env, flags_default)//'"' // & - ' --c-flag:: "'//get_env(cflags_env, flags_default)//'"' // & - ' --link-flag:: "'//get_env(ldflags_env, flags_default)//'"' + ' --compiler "'//get_fpm_env(fc_env, fc_default)//'"' // & + ' --c-compiler "'//get_fpm_env(cc_env, cc_default)//'"' // & + ' --archiver "'//get_fpm_env(ar_env, ar_default)//'"' // & + ' --flag:: "'//get_fpm_env(fflags_env, flags_default)//'"' // & + ' --c-flag:: "'//get_fpm_env(cflags_env, flags_default)//'"' // & + ' --link-flag:: "'//get_fpm_env(ldflags_env, flags_default)//'"' ! now set subcommand-specific help text and process commandline ! arguments. Then call subcommand routine @@ -242,6 +265,8 @@ subroutine get_command_line_settings(cmd_settings) if(names(i).eq.'..')names(i)='*' enddo + c_compiler = sget('c-compiler') + archiver = sget('archiver') allocate(fpm_run_settings :: cmd_settings) val_runner=sget('runner') if(specified('runner') .and. val_runner.eq.'')val_runner='echo' @@ -249,6 +274,8 @@ subroutine get_command_line_settings(cmd_settings) & args=remaining,& & profile=val_profile,& & compiler=val_compiler, & + & c_compiler=c_compiler, & + & archiver=archiver, & & flag=val_flag, & & cflag=val_cflag, & & ldflag=val_ldflag, & @@ -266,10 +293,14 @@ subroutine get_command_line_settings(cmd_settings) call check_build_vals() + c_compiler = sget('c-compiler') + archiver = sget('archiver') allocate( fpm_build_settings :: cmd_settings ) cmd_settings=fpm_build_settings( & & profile=val_profile,& & compiler=val_compiler, & + & c_compiler=c_compiler, & + & archiver=archiver, & & flag=val_flag, & & cflag=val_cflag, & & ldflag=val_ldflag, & @@ -399,11 +430,15 @@ subroutine get_command_line_settings(cmd_settings) call check_build_vals() + c_compiler = sget('c-compiler') + archiver = sget('archiver') allocate(install_settings) install_settings = fpm_install_settings(& list=lget('list'), & profile=val_profile,& compiler=val_compiler, & + c_compiler=c_compiler, & + archiver=archiver, & flag=val_flag, & cflag=val_cflag, & ldflag=val_ldflag, & @@ -446,6 +481,8 @@ subroutine get_command_line_settings(cmd_settings) if(names(i).eq.'..')names(i)='*' enddo + c_compiler = sget('c-compiler') + archiver = sget('archiver') allocate(fpm_test_settings :: cmd_settings) val_runner=sget('runner') if(specified('runner') .and. val_runner.eq.'')val_runner='echo' @@ -453,6 +490,8 @@ subroutine get_command_line_settings(cmd_settings) & args=remaining, & & profile=val_profile, & & compiler=val_compiler, & + & c_compiler=c_compiler, & + & archiver=archiver, & & flag=val_flag, & & cflag=val_cflag, & & ldflag=val_ldflag, & @@ -700,12 +739,11 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& + help_text_compiler, & help_text_flag, & ' --list List candidates instead of building or running them. On ', & ' the fpm(1) command this shows a brief list of subcommands.', & ' --runner CMD Provides a command to prefix program execution paths. ', & - ' --compiler COMPILER_NAME Compiler name. The environment variable ', & - ' FC sets the default. ', & ' -- ARGS Arguments to pass to executables. ', & ' ', & 'VALID FOR ALL SUBCOMMANDS ', & @@ -823,10 +861,8 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& + help_text_compiler, & help_text_flag, & - ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & - ' "gfortran" unless set by the environment ', & - ' variable FC. ', & ' --runner CMD A command to prefix the program execution paths with. ', & ' see "fpm help runner" for further details. ', & ' --list list pathname of candidates instead of running them. Note ', & @@ -893,10 +929,8 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& + help_text_compiler, & help_text_flag, & - ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & - ' "gfortran" unless set by the environment ', & - ' variable FC. ', & ' --list list candidates instead of building or running them ', & ' --show-model show the model and exit (do not build) ', & ' --help print this help and exit ', & @@ -1071,10 +1105,8 @@ subroutine set_help() ' high optimization and "debug" for full debug options.',& ' If --flag is not specified the "debug" flags are the',& ' default. ',& + help_text_compiler, & help_text_flag, & - ' --compiler COMPILER_NAME Specify a compiler name. The default is ', & - ' "gfortran" unless set by the environment ', & - ' variable FC. ', & ' --runner CMD A command to prefix the program execution paths with. ', & ' see "fpm help runner" for further details. ', & ' --list list candidates instead of building or running them ', & @@ -1178,14 +1210,15 @@ subroutine get_char_arg(var, arg) end subroutine get_char_arg - !> Get Fortran compiler from environment. - function get_fc_env() result(fc) - character(len=:), allocatable :: fc + !> Get an environment variable for fpm + function get_fpm_env(env, default) result(val) + character(len=*), intent(in) :: env + character(len=*), intent(in) :: default + character(len=:), allocatable :: val - character(len=*), parameter :: fc_env = "FC", fc_env_long = "FPM_COMPILER" - character(len=*), parameter :: fc_default = "gfortran" + character(len=*), parameter :: fpm_prefix = "FPM_" - fc = get_env(fc_env_long, get_env(fc_env, fc_default)) - end function get_fc_env + val = get_env(fpm_prefix//val, get_env(env, default)) + end function get_fpm_env end module fpm_command_line diff --git a/src/fpm_compiler.f90 b/src/fpm_compiler.f90 index 1969f8d478..34ac941de6 100644 --- a/src/fpm_compiler.f90 +++ b/src/fpm_compiler.f90 @@ -596,44 +596,62 @@ end function is_unknown !> Create new compiler instance -subroutine new_compiler(self, fc) - !> Fortran compiler name or path - character(len=*), intent(in) :: fc +subroutine new_compiler(self, fc, cc) !> New instance of the compiler type(compiler_t), intent(out) :: self - - character(len=*), parameter :: cc_env = "CC" + !> Fortran compiler name or path + character(len=*), intent(in) :: fc + !> C compiler name or path + character(len=*), intent(in) :: cc self%id = get_compiler_id(fc) self%fc = fc - call get_default_c_compiler(self%fc, self%cc) - self%cc = get_env(cc_env, self%cc) + if (len_trim(cc) > 0) then + self%cc = cc + else + call get_default_c_compiler(self%fc, self%cc) + end if end subroutine new_compiler !> Create new archiver instance -subroutine new_archiver(self) +subroutine new_archiver(self, ar) !> New instance of the archiver type(archiver_t), intent(out) :: self - integer :: estat, os_type + !> User provided archiver command + character(len=*), intent(in) :: ar - character(len=:), allocatable :: ar - character(len=*), parameter :: arflags = " -rs " + integer :: estat, os_type - ar = get_env("AR", "ar") + character(len=*), parameter :: arflags = " -rs ", libflags = " /OUT:" - os_type = get_os_type() - if (os_type /= OS_WINDOWS .and. os_type /= OS_UNKNOWN) then + if (len_trim(ar) > 0) then + ! Check first for ar-like commands + if (check_compiler(ar, "ar")) then self%ar = ar//arflags + end if + + ! Check for lib-like commands + if (check_compiler(ar, "lib")) then + self%ar = ar//libflags + end if + + ! Fallback and assume ar-like behaviour + self%ar = ar//arflags else - call execute_command_line(ar//" --version > "//get_temp_filename()//" 2>&1", & - & exitstat=estat) + os_type = get_os_type() + if (os_type /= OS_WINDOWS .and. os_type /= OS_UNKNOWN) then + self%ar = "ar"//arflags + else + call execute_command_line("ar --version > "//get_temp_filename()//" 2>&1", & + & exitstat=estat) if (estat /= 0) then - self%ar = "lib /OUT:" + self%ar = "lib"//libflags else - self%ar = ar//arflags + self%ar = "ar"//arflags end if + end if end if self%use_response_file = os_type == OS_WINDOWS self%echo = .true. From a53eb7c32644501b3bec840161902c08b2619989 Mon Sep 17 00:00:00 2001 From: Sebastian Ehlert <28669218+awvwgk@users.noreply.github.com> Date: Mon, 30 Aug 2021 20:32:24 +0200 Subject: [PATCH 4/4] Only use FPM_ prefixed environment variables --- src/fpm_command_line.f90 | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/fpm_command_line.f90 b/src/fpm_command_line.f90 index 13624462a3..2c049204ec 100644 --- a/src/fpm_command_line.f90 +++ b/src/fpm_command_line.f90 @@ -120,55 +120,46 @@ module fpm_command_line character(len=80), parameter :: help_text_compiler(*) = [character(len=80) :: & ' --compiler NAME Specify a compiler name. The default is "gfortran"',& - ' unless set by the environment variable FPM_FC or FC.',& + ' unless set by the environment variable FPM_FC.',& ' --c-compiler NAME Specify the C compiler name. By default automatic determined',& - ' unless set by the environment variable FPM_CC or CC.',& + ' unless set by the environment variable FPM_CC.',& ' --archiver NAME Specify the archiver name. By default automatic determined',& - ' unless set by the environment variable FPM_AR or AR.'& + ' unless set by the environment variable FPM_AR.'& ] character(len=80), parameter :: help_text_flag(*) = [character(len=80) :: & ' --flag FFLAGS selects compile arguments for the build, the default',& - ' value is set by the FFLAGS environment variable.', & + ' value is set by the FPM_FFLAGS environment variable.', & ' These are added to the profile options if --profile', & ' is specified, else these options override the defaults.',& ' Note object and .mod directory locations are always',& ' built in.',& ' --c-flag CFLAGS selects compile arguments specific for C source in the build.',& - ' The default value is set by the CFLAGS environment variable.',& + ' The default value is set by the FPM_CFLAGS environment variable.',& ' --link-flag LDFLAGS',& ' select arguments passed to the linker for the build.',& - ' The default value is set by the LDFLAGS environment variable.'& + ' The default value is set by the FPM_LDFLAGS environment variable.'& ] character(len=80), parameter :: help_text_environment(*) = [character(len=80) :: & 'ENVIRONMENT VARIABLES',& - ' FPM_FC, FC sets the path to the Fortran compiler used for the build,', & - ' FPM_FC will take preference over FC, if both are set,', & + ' FPM_FC sets the path to the Fortran compiler used for the build,', & ' will be overwritten by --compiler command line option', & '', & - ' FPM_FFLAGS, FFLAGS',& - ' sets the arguments for the Fortran compiler', & - ' FPM_FFLAGS will take preference over FFLAGS, if both are set,', & + ' FPM_FFLAGS sets the arguments for the Fortran compiler', & ' will be overwritten by --flag command line option', & '', & - ' FPM_CC, CC sets the path to the C compiler used for the build,', & - ' FPM_CC will take preference over CC, if both are set,', & + ' FPM_CC sets the path to the C compiler used for the build,', & ' will be overwritten by --c-compiler command line option', & '', & - ' FPM_CFLAGS, CFLAGS',& - ' sets the arguments for the C compiler', & - ' FPM_CFLAGS will take preference over CFLAGS, if both are set,', & + ' FPM_CFLAGS sets the arguments for the C compiler', & ' will be overwritten by --c-flag command line option', & '', & - ' FPM_AR, AR sets the path to the archiver used for the build,', & - ' FPM_AR will take preference over AR, if both are set,', & + ' FPM_AR sets the path to the archiver used for the build,', & ' will be overwritten by --archiver command line option', & '', & - ' FPM_LDFLAGS, LDFLAGS',& - ' sets additional link arguments for creating executables', & - ' FPM_LDFLAGS will take preference over LDFLAGS, if both are set,', & + ' FPM_LDFLAGS sets additional link arguments for creating executables', & ' will be overwritten by --link-flag command line option' & ] @@ -1210,7 +1201,8 @@ subroutine get_char_arg(var, arg) end subroutine get_char_arg - !> Get an environment variable for fpm + !> Get an environment variable for fpm, this routine ensures that every variable + !> used by fpm is prefixed with FPM_. function get_fpm_env(env, default) result(val) character(len=*), intent(in) :: env character(len=*), intent(in) :: default @@ -1218,7 +1210,7 @@ function get_fpm_env(env, default) result(val) character(len=*), parameter :: fpm_prefix = "FPM_" - val = get_env(fpm_prefix//val, get_env(env, default)) + val = get_env(fpm_prefix//val, default) end function get_fpm_env end module fpm_command_line