Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions ci/run_tests.bat
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,28 @@ if errorlevel 1 exit 1
%fpm_path% run --target gomp_test
if errorlevel 1 exit 1


cd ..\fortran_includes
if errorlevel 1 exit 1

del /q /f build
%fpm_path% build
if errorlevel 1 exit 1


cd ..\c_includes
if errorlevel 1 exit 1

del /q /f build
%fpm_path% build
if errorlevel 1 exit 1


cd ..\c_header_only
if errorlevel 1 exit 1

del /q /f build
%fpm_path% build
if errorlevel 1 exit 1

cd ..\..
9 changes: 9 additions & 0 deletions ci/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,14 @@ cd ../link_executable
"${f_fpm_path}" build
"${f_fpm_path}" run --target gomp_test

cd ../fortran_includes
"${f_fpm_path}" build

cd ../c_includes
"${f_fpm_path}" build

cd ../c_header_only
"${f_fpm_path}" build

# Cleanup
rm -rf ./*/build
3 changes: 3 additions & 0 deletions example_packages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ the features demonstrated in each package and which versions of fpm are supporte
| Name | Features | Bootstrap (Haskell) fpm | fpm |
|---------------------|---------------------------------------------------------------|:-----------------------:|:---:|
| auto_discovery_off | Default layout with auto-discovery disabled | N | Y |
| c_header_only | C header-only library | N | Y |
| c_includes | C library with c include directory and dependency includes | N | Y |
| circular_example | Local path dependency; circular dependency | Y | Y |
| circular_test | Local path dependency; circular dependency | Y | Y |
| fortran_includes | Fortran library with explicit include directory | Y | N |
| hello_complex | Non-standard directory layout; multiple tests and executables | Y | Y |
| hello_complex_2 | Auto-discovery of tests and executables with modules | N | Y |
| hello_fpm | App-only; local path dependency | Y | Y |
Expand Down
1 change: 1 addition & 0 deletions example_packages/c_header_only/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/*
1 change: 1 addition & 0 deletions example_packages/c_header_only/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name = "c_header_only"
1 change: 1 addition & 0 deletions example_packages/c_header_only/include/c_header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int printf ( const char * format, ... );
1 change: 1 addition & 0 deletions example_packages/c_includes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/*
4 changes: 4 additions & 0 deletions example_packages/c_includes/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name = "c_includes"

[dependencies]
c_header_only = { path = "../c_header_only"}
4 changes: 4 additions & 0 deletions example_packages/c_includes/include/lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Include from "c_header_only" dependency
#include "c_header.h"

int test(const int a);
7 changes: 7 additions & 0 deletions example_packages/c_includes/src/lib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "lib.h"

int test(const int a){

return printf("input: %d\n", a);

}
1 change: 1 addition & 0 deletions example_packages/fortran_includes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/*
4 changes: 4 additions & 0 deletions example_packages/fortran_includes/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name = "fortran_includes"

[library]
include-dir = "inc"
1 change: 1 addition & 0 deletions example_packages/fortran_includes/inc/parameters.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
integer, parameter :: dp = kind(0.d0)
14 changes: 14 additions & 0 deletions example_packages/fortran_includes/src/lib.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module test_mod
implicit none

include "parameters.f90"

contains

subroutine test_sub(a)
real(dp), intent(in) :: a

write(*,*) 'a: ', a
end subroutine test_sub

end module test_mod
1 change: 1 addition & 0 deletions example_packages/link_executable/include/test.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
real, parameter :: a = 2.0
45 changes: 31 additions & 14 deletions fpm/src/fpm.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module fpm
use fpm_strings, only: string_t, operator(.in.), glob, join
use fpm_strings, only: string_t, operator(.in.), glob, join, string_cat
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
Expand Down Expand Up @@ -39,17 +39,14 @@ subroutine build_model(model, settings, package, error)
type(package_config_t), intent(in) :: package
type(error_t), allocatable, intent(out) :: error

integer :: i
integer :: i, j
type(package_config_t) :: dependency
character(len=:), allocatable :: manifest, lib_dir

if(settings%verbose)then
write(*,*)'<INFO>BUILD_NAME:',settings%build_name
write(*,*)'<INFO>COMPILER: ',settings%compiler
endif
type(string_t) :: include_dir

model%package_name = package%name

allocate(model%include_dirs(0))
allocate(model%link_libraries(0))

call new_dependency_tree(model%deps, cache=join_path("build", "cache.toml"))
Expand All @@ -73,9 +70,6 @@ subroutine build_model(model, settings, package, error)
& join_path(model%output_directory,model%package_name), &
& model%fortran_compile_flags)
model%fortran_compile_flags = settings%flag // model%fortran_compile_flags
if(settings%verbose)then
write(*,*)'<INFO>COMPILER OPTIONS: ', model%fortran_compile_flags
endif

allocate(model%packages(model%deps%ndep))

Expand Down Expand Up @@ -147,12 +141,28 @@ subroutine build_model(model, settings, package, error)
if (allocated(error)) exit

model%packages(i)%name = dependency%name
if (.not.allocated(model%packages(i)%sources)) allocate(model%packages(i)%sources(0))

if (allocated(dependency%library)) then
lib_dir = join_path(dep%proj_dir, dependency%library%source_dir)
call add_sources_from_dir(model%packages(i)%sources, lib_dir, FPM_SCOPE_LIB, &
error=error)
if (allocated(error)) exit

if (allocated(dependency%library%source_dir)) then
lib_dir = join_path(dep%proj_dir, dependency%library%source_dir)
if (is_dir(lib_dir)) then
call add_sources_from_dir(model%packages(i)%sources, lib_dir, FPM_SCOPE_LIB, &
error=error)
if (allocated(error)) exit
end if
end if

if (allocated(dependency%library%include_dir)) then
do j=1,size(dependency%library%include_dir)
include_dir%s = join_path(dep%proj_dir, dependency%library%include_dir(j)%s)
if (is_dir(include_dir%s)) then
model%include_dirs = [model%include_dirs, include_dir]
end if
end do
end if

end if

if (allocated(dependency%build%link)) then
Expand All @@ -162,6 +172,13 @@ subroutine build_model(model, settings, package, error)
end do
if (allocated(error)) return

if (settings%verbose) then
write(*,*)'<INFO> BUILD_NAME: ',settings%build_name
write(*,*)'<INFO> COMPILER: ',settings%compiler
write(*,*)'<INFO> COMPILER OPTIONS: ', model%fortran_compile_flags
write(*,*)'<INFO> INCLUDE DIRECTORIES: [', string_cat(model%include_dirs,','),']'
end if

end subroutine build_model


Expand Down
8 changes: 6 additions & 2 deletions fpm/src/fpm/manifest.f90
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ module fpm_manifest
use fpm_error, only : error_t, fatal_error, file_not_found_error
use fpm_toml, only : toml_table, read_package_file
use fpm_manifest_test, only : test_config_t
use fpm_filesystem, only: join_path, exists, dirname
use fpm_filesystem, only: join_path, exists, dirname, is_dir
use fpm_strings, only: string_t
implicit none
private

Expand All @@ -35,6 +36,7 @@ subroutine default_library(self)
type(library_config_t), intent(out) :: self

self%source_dir = "src"
self%include_dir = [string_t("include")]

end subroutine default_library

Expand Down Expand Up @@ -140,7 +142,9 @@ subroutine package_defaults(package, root, error)

! Populate library in case we find the default src directory
if (.not.allocated(package%library) .and. &
& exists(join_path(root, "src"))) then
& (is_dir(join_path(root, "src")) .or. &
& is_dir(join_path(root, "include")))) then

allocate(package%library)
call default_library(package%library)
end if
Expand Down
18 changes: 17 additions & 1 deletion fpm/src/fpm/manifest/library.f90
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
!>```toml
!>[library]
!>source-dir = "path"
!>include-dir = ["path1","path2"]
!>build-script = "file"
!>```
module fpm_manifest_library
use fpm_error, only : error_t, syntax_error
use fpm_strings, only: string_t, string_cat
use fpm_toml, only : toml_table, toml_key, toml_stat, get_value
implicit none
private
Expand All @@ -22,6 +24,9 @@ module fpm_manifest_library
!> Source path prefix
character(len=:), allocatable :: source_dir

!> Include path prefix
type(string_t), allocatable :: include_dir(:)

!> Alternative build script to be invoked
character(len=:), allocatable :: build_script

Expand Down Expand Up @@ -54,6 +59,14 @@ subroutine new_library(self, table, error)
call get_value(table, "source-dir", self%source_dir, "src")
call get_value(table, "build-script", self%build_script)

call get_value(table, "include-dir", self%include_dir, error)
if (allocated(error)) return

! Set default value of include-dir if not found in manifest
if (.not.allocated(self%include_dir)) then
self%include_dir = [string_t("include")]
end if

end subroutine new_library


Expand All @@ -80,7 +93,7 @@ subroutine check(table, error)
call syntax_error(error, "Key "//list(ikey)%key//" is not allowed in library")
exit

case("source-dir", "build-script")
case("source-dir", "include-dir", "build-script")
continue

end select
Expand Down Expand Up @@ -116,6 +129,9 @@ subroutine info(self, unit, verbosity)
if (allocated(self%source_dir)) then
write(unit, fmt) "- source directory", self%source_dir
end if
if (allocated(self%include_dir)) then
write(unit, fmt) "- include directory", string_cat(self%include_dir,",")
end if
if (allocated(self%build_script)) then
write(unit, fmt) "- custom build", self%build_script
end if
Expand Down
3 changes: 3 additions & 0 deletions fpm/src/fpm_model.f90
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ module fpm_model
!> Base directory for build
character(:), allocatable :: output_directory

!> Include directories
type(string_t), allocatable :: include_dirs(:)

!> Native libraries to link against
type(string_t), allocatable :: link_libraries(:)

Expand Down
13 changes: 13 additions & 0 deletions fpm/src/fpm_strings.f90
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ module fpm_strings
module procedure str_int, str_int64, str_logical
end interface

interface string_t
module procedure new_string_t
end interface string_t

contains

!> test if a CHARACTER string ends with a specified suffix
Expand Down Expand Up @@ -193,6 +197,15 @@ elemental pure function lower(str,begin,end) result (string)

end function lower

!> Helper function to generate a new string_t instance
!> (Required due to the allocatable component)
function new_string_t(s) result(string)
character(*), intent(in) :: s
type(string_t) :: string

string%s = s

end function new_string_t

!> Check if array of TYPE(STRING_T) matches a particular CHARACTER string
!!
Expand Down
25 changes: 23 additions & 2 deletions fpm/src/fpm_targets.f90
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,20 @@ subroutine build_target_list(targets,model)
!> The package model from which to construct the target list
type(fpm_model_t), intent(inout), target :: model

integer :: i, j
integer :: i, j, n_source
character(:), allocatable :: xsuffix, exe_dir
type(build_target_t), pointer :: dep
logical :: with_lib

! Check for empty build (e.g. header-only lib)
n_source = sum([(size(model%packages(j)%sources), &
j=1,size(model%packages))])

if (n_source < 1) then
allocate(targets(0))
return
end if

if (get_os_type() == OS_WINDOWS) then
xsuffix = '.exe'
else
Expand Down Expand Up @@ -433,24 +442,36 @@ subroutine resolve_target_linking(targets, model)

integer :: i
character(:), allocatable :: global_link_flags
character(:), allocatable :: global_compile_flags

if (size(targets) == 0) return

if (targets(1)%ptr%target_type == FPM_TARGET_ARCHIVE) then
global_link_flags = targets(1)%ptr%output_file
else
allocate(character(0) :: global_link_flags)
end if

global_compile_flags = model%fortran_compile_flags

if (allocated(model%link_libraries)) then
if (size(model%link_libraries) > 0) then
global_link_flags = global_link_flags // " -l" // string_cat(model%link_libraries," -l")
end if
end if

if (allocated(model%include_dirs)) then
if (size(model%include_dirs) > 0) then
global_compile_flags = global_compile_flags // &
& " -I" // string_cat(model%include_dirs," -I")
end if
end if

do i=1,size(targets)

associate(target => targets(i)%ptr)

target%compile_flags = model%fortran_compile_flags
target%compile_flags = global_compile_flags

allocate(target%link_objects(0))

Expand Down
Loading