Skip to content

Commit

Permalink
Merge pull request #575 from awvwgk/build-dirs
Browse files Browse the repository at this point in the history
Enable multiple build output directories
  • Loading branch information
awvwgk authored Oct 10, 2021
2 parents d129243 + 6f816ad commit df9b01a
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 84 deletions.
13 changes: 5 additions & 8 deletions src/fpm.f90
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ subroutine build_model(model, settings, package, error)

logical :: duplicates_found = .false.
type(string_t) :: include_dir
character(len=16) :: build_name

model%package_name = package%name

Expand Down Expand Up @@ -72,21 +71,19 @@ subroutine build_model(model, settings, package, error)
flags = flags // model%compiler%get_default_flags(settings%profile == "release")
end select
end if

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))') &
"<WARN>", "Unknown compiler", model%compiler%fc, "requested!", &
"Defaults for this compiler might be incorrect"
end if
model%output_directory = join_path('build',basename(model%compiler%fc)//'_'//build_name)
model%build_prefix = join_path("build", basename(model%compiler%fc))

model%fortran_compile_flags = flags // " " // &
& model%compiler%get_module_flag(join_path(model%output_directory, model%package_name))
model%fortran_compile_flags = flags
model%c_compile_flags = cflags
model%link_flags = ldflags

model%include_tests = settings%build_tests

Expand Down Expand Up @@ -196,7 +193,7 @@ subroutine build_model(model, settings, package, error)
if (allocated(error)) return

if (settings%verbose) then
write(*,*)'<INFO> BUILD_NAME: ',build_name
write(*,*)'<INFO> BUILD_NAME: ',model%build_prefix
write(*,*)'<INFO> COMPILER: ',model%compiler%fc
write(*,*)'<INFO> C COMPILER: ',model%compiler%cc
write(*,*)'<INFO> COMPILER OPTIONS: ', model%fortran_compile_flags
Expand Down
63 changes: 25 additions & 38 deletions src/fpm/cmd/install.f90
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ module fpm_cmd_install
use fpm_manifest, only : package_config_t, get_package_data
use fpm_model, only : fpm_model_t, FPM_SCOPE_APP
use fpm_targets, only: targets_from_sources, build_target_t, &
build_target_ptr, FPM_TARGET_EXECUTABLE
build_target_ptr, FPM_TARGET_EXECUTABLE, &
filter_library_targets, filter_executable_targets, filter_modules
use fpm_strings, only : string_t, resize
implicit none
private
Expand All @@ -28,6 +29,7 @@ subroutine cmd_install(settings)
type(build_target_ptr), allocatable :: targets(:)
type(installer_t) :: installer
character(len=:), allocatable :: lib, dir
type(string_t), allocatable :: list(:)
logical :: installable

call get_package_data(package, "fpm.toml", error, apply_defaults=.true.)
Expand Down Expand Up @@ -61,13 +63,15 @@ subroutine cmd_install(settings)
verbosity=merge(2, 1, settings%verbose))

if (allocated(package%library) .and. package%install%library) then
dir = join_path(model%output_directory, model%package_name)
lib = "lib"//model%package_name//".a"
call installer%install_library(join_path(dir, lib), error)
call handle_error(error)
call filter_library_targets(targets, list)

call install_module_files(installer, dir, error)
call handle_error(error)
if (size(list) > 0) then
call installer%install_library(list(1)%s, error)
call handle_error(error)

call install_module_files(installer, targets, error)
call handle_error(error)
end if
end if

if (allocated(package%executable)) then
Expand All @@ -85,24 +89,17 @@ subroutine install_info(unit, package, model, targets)

integer :: ii, ntargets
character(len=:), allocatable :: lib
type(string_t), allocatable :: install_target(:)
type(string_t), allocatable :: install_target(:), temp(:)

call resize(install_target)
allocate(install_target(0))

ntargets = 0
if (allocated(package%library) .and. package%install%library) then
ntargets = ntargets + 1
lib = join_path(model%output_directory, model%package_name, &
"lib"//model%package_name//".a")
install_target(ntargets)%s = lib
end if
do ii = 1, size(targets)
if (is_executable_target(targets(ii)%ptr)) then
if (ntargets >= size(install_target)) call resize(install_target)
ntargets = ntargets + 1
install_target(ntargets)%s = targets(ii)%ptr%output_file
end if
end do
call filter_library_targets(targets, temp)
install_target = [install_target, temp]

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

ntargets = size(install_target)

write(unit, '("#", *(1x, g0))') &
"total number of installable targets:", ntargets
Expand All @@ -112,20 +109,18 @@ subroutine install_info(unit, package, model, targets)

end subroutine install_info

subroutine install_module_files(installer, dir, error)
subroutine install_module_files(installer, targets, error)
type(installer_t), intent(inout) :: installer
character(len=*), intent(in) :: dir
type(build_target_ptr), intent(in) :: targets(:)
type(error_t), allocatable, intent(out) :: error
type(string_t), allocatable :: modules(:)
integer :: ii

call list_files(dir, modules, recurse=.false.)
call filter_modules(targets, modules)

do ii = 1, size(modules)
if (is_module_file(modules(ii)%s)) then
call installer%install_header(modules(ii)%s, error)
if (allocated(error)) exit
end if
call installer%install_header(modules(ii)%s//".mod", error)
if (allocated(error)) exit
end do
if (allocated(error)) return

Expand Down Expand Up @@ -157,14 +152,6 @@ elemental function is_executable_target(target_ptr) result(is_exe)
end if
end function is_executable_target

elemental function is_module_file(name) result(is_mod)
character(len=*), intent(in) :: name
logical :: is_mod
integer :: ll
ll = len(name)
is_mod = name(max(1, ll-3):ll) == ".mod"
end function is_module_file

subroutine handle_error(error)
type(error_t), intent(in), optional :: error
if (present(error)) then
Expand Down
18 changes: 15 additions & 3 deletions src/fpm_backend.f90
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module fpm_backend
use fpm_environment, only: run, get_os_type, OS_WINDOWS
use fpm_filesystem, only: basename, dirname, join_path, exists, mkdir
use fpm_model, only: fpm_model_t
use fpm_strings, only: string_t, operator(.in.)
use fpm_targets, only: build_target_t, build_target_ptr, FPM_TARGET_OBJECT, &
FPM_TARGET_C_OBJECT, FPM_TARGET_ARCHIVE, FPM_TARGET_EXECUTABLE
implicit none
Expand All @@ -50,11 +51,22 @@ subroutine build_package(targets,model)
type(build_target_ptr), allocatable :: queue(:)
integer, allocatable :: schedule_ptr(:), stat(:)
logical :: build_failed, skip_current
type(string_t), allocatable :: build_dirs(:)
type(string_t) :: temp

! Need to make output directory for include (mod) files
if (.not.exists(join_path(model%output_directory,model%package_name))) then
call mkdir(join_path(model%output_directory,model%package_name))
end if
allocate(build_dirs(0))
do i = 1, size(targets)
associate(target => targets(i)%ptr)
if (target%output_dir .in. build_dirs) cycle
temp%s = target%output_dir
build_dirs = [build_dirs, temp]
end associate
end do

do i = 1, size(build_dirs)
call mkdir(build_dirs(i)%s)
end do

! Perform depth-first topological sort of targets
do i=1,size(targets)
Expand Down
1 change: 0 additions & 1 deletion src/fpm_compiler.f90
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,6 @@ function get_module_flag(self, path) result(flags)
flags = "-qmoddir "//path

end select
flags = flags//" "//self%get_include_flag(path)

end function get_module_flag

Expand Down
5 changes: 2 additions & 3 deletions src/fpm_model.f90
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ module fpm_model
character(:), allocatable :: link_flags

!> Base directory for build
character(:), allocatable :: output_directory
character(:), allocatable :: build_prefix

!> Include directories
type(string_t), allocatable :: include_dirs(:)
Expand Down Expand Up @@ -284,8 +284,7 @@ function info_model(model) result(s)
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 // '"'
s = s // ', build_prefix="' // model%build_prefix // '"'
! type(string_t), allocatable :: link_libraries(:)
s = s // ", link_libraries=["
do i = 1, size(model%link_libraries)
Expand Down
Loading

0 comments on commit df9b01a

Please sign in to comment.