Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tree shaking for modules #676

Merged
merged 22 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
39d67cb
Refactor parsing: immediately skip commented lines
LKedward Mar 13, 2022
20643a4
Refactor parsing: stop parsing line after successful parse
LKedward Mar 13, 2022
17ac86b
Update parsing: to detect subprograms outside modules
LKedward Mar 13, 2022
219c98c
Add: tree-shaking/pruning of unused modules
LKedward Mar 13, 2022
7d65003
Add: test package for tree-shaking
LKedward Mar 13, 2022
4eedd3a
Add: test case for tree shaking of unused modules
LKedward Mar 13, 2022
4c05a6f
Add: parsing test case where we can't detect end module statement
LKedward Mar 13, 2022
089f9dc
Update: tree-shaking test for external function case
LKedward Mar 13, 2022
69a5673
Update: tree-shaking to handle submodules correctly
LKedward Mar 13, 2022
5d044df
Add: test package for submodule tree-shaking
LKedward Mar 13, 2022
6252f16
Merge branch 'fortran-lang:main' into tree-shaking
LKedward Mar 13, 2022
cdc7908
Merge branch 'fortran-lang:main' into tree-shaking
LKedward Mar 14, 2022
142d259
Add: --no-prune argument to disable tree-shaking/pruning of dependencies
LKedward Mar 19, 2022
c5c7e1a
Merge branch 'tree-shaking' of github.com:LKedward/fpm into tree-shaking
LKedward Mar 19, 2022
e515796
Update: unit tests with new prune flag.
LKedward Mar 19, 2022
28dcdc4
Update: to allow pruning based on root package modules
LKedward Mar 19, 2022
b0c855d
Update: enumeration of used modules for efficiency
LKedward May 9, 2022
e08b64a
Fix: issue with pruning of non-module dependencies
LKedward May 9, 2022
cfb0a51
Update: source parsing to skip pre-processor lines
LKedward May 9, 2022
722a325
Update: source parsing test with preprocessor line
LKedward May 9, 2022
895f774
Update: to detect exported C API in modules via bind(C)
LKedward May 29, 2022
13f9c85
Update: parsing with parse_sequence helper fcn
LKedward May 29, 2022
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
18 changes: 18 additions & 0 deletions ci/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,24 @@ test ! -x ./build/gfortran_*/app/unused
test ! -x ./build/gfortran_*/test/unused_test
popd

pushd tree_shake
"$fpm" build
"$fpm" run
"$fpm" test
test ! -e ./build/gfortran_*/tree_shake/src_farewell_m.f90.o
test ! -e ./build/gfortran_*/tree_shake/src_farewell_m.f90.o.log
popd

pushd submodule_tree_shake
"$fpm" run
test ! -e ./build/gfortran_*/submodule_tree_shake/src_parent_unused.f90.o
test ! -e ./build/gfortran_*/submodule_tree_shake/src_parent_unused.f90.o.log
test ! -e ./build/gfortran_*/submodule_tree_shake/src_child_unused.f90.o
test ! -e ./build/gfortran_*/submodule_tree_shake/src_child_unused.f90.o.log
test ! -e ./build/gfortran_*/submodule_tree_shake/src_grandchild.f90.o
test ! -e ./build/gfortran_*/submodule_tree_shake/src_grandchild.f90.o.log
popd

pushd version_file
"$fpm" build
"$fpm" run
Expand Down
2 changes: 2 additions & 0 deletions example_packages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ the features demonstrated in each package and which versions of fpm are supporte
| makefile_complex | External build command (makefile); local path dependency | Y | N |
| program_with_module | App-only; module+program in single source file | Y | Y |
| submodules | Lib-only; submodules (3 levels) | N | Y |
| tree_shake | Test tree-shaking/pruning of unused module dependencies | N | Y |
| submodule_tree_shake| Test tree-shaking/pruning with submodules dependencies | N | Y |
| link_external | Link external library | N | Y |
| link_executable | Link external library to a single executable | N | Y |
| version_file | Read version number from a file in the project root | N | Y |
Expand Down
1 change: 1 addition & 0 deletions example_packages/submodule_tree_shake/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/*
9 changes: 9 additions & 0 deletions example_packages/submodule_tree_shake/app/main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
program test
use parent

integer :: a, b

call my_sub1(a)
call my_sub2(b)

end program test
1 change: 1 addition & 0 deletions example_packages/submodule_tree_shake/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name = "submodule_tree_shake"
16 changes: 16 additions & 0 deletions example_packages/submodule_tree_shake/src/child1.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
submodule(parent) child1
implicit none

interface
module function my_fun() result (b)
integer :: b
end function my_fun
end interface

contains

module procedure my_sub1
a = 1
end procedure my_sub1

end submodule child1
10 changes: 10 additions & 0 deletions example_packages/submodule_tree_shake/src/child2.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
submodule(parent) child2
implicit none

contains

module procedure my_sub2
a = 2
end procedure my_sub2

end submodule child2
10 changes: 10 additions & 0 deletions example_packages/submodule_tree_shake/src/child_unused.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
submodule(parent_unused) child_unused
implicit none

contains

module procedure unused_sub
a = 1
end procedure unused_sub

end submodule child_unused
10 changes: 10 additions & 0 deletions example_packages/submodule_tree_shake/src/grandchild.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
submodule(parent:child1) grandchild
implicit none

contains

module procedure my_fun
b = 2
end procedure my_fun

end submodule grandchild
15 changes: 15 additions & 0 deletions example_packages/submodule_tree_shake/src/parent.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module parent
implicit none

interface

module subroutine my_sub1(a)
integer, intent(out) :: a
end subroutine my_sub1

module subroutine my_sub2(a)
integer, intent(out) :: a
end subroutine my_sub2
end interface

end module parent
12 changes: 12 additions & 0 deletions example_packages/submodule_tree_shake/src/parent_unused.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module parent_unused
implicit none

interface

module subroutine unused_sub(a)
integer, intent(out) :: a
end subroutine unused_sub

end interface

end module parent_unused
1 change: 1 addition & 0 deletions example_packages/tree_shake/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/*
15 changes: 15 additions & 0 deletions example_packages/tree_shake/app/say_Hello.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
program say_Hello
use greet_m, only: make_greeting

implicit none

interface
function external_function() result(i)
integer :: i
end function external_function
end interface

print *, make_greeting("World")
print *, external_function()

end program say_Hello
1 change: 1 addition & 0 deletions example_packages/tree_shake/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name = "tree_shake"
15 changes: 15 additions & 0 deletions example_packages/tree_shake/src/extra_m.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
! This module is not used by any other sources,
! however because it also contains an external function
! it cannot be dropped during tree-shaking/pruning
module extra_m
use subdir_constants, only: FAREWELL_STR
implicit none
private

integer, parameter :: m = 0
end

function external_function() result(i)
integer :: i
i = 1
end function external_function
17 changes: 17 additions & 0 deletions example_packages/tree_shake/src/farewell_m.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
! This module is not used by any other sources
! and only contains a module (no non-module subprograms),
! therefore it should be dropped during tree-shaking/pruning
module farewell_m
use subdir_constants, only: FAREWELL_STR
implicit none
private

public :: make_farewell
contains
function make_farewell(name) result(greeting)
character(len=*), intent(in) :: name
character(len=:), allocatable :: greeting

greeting = FAREWELL_STR // name // "!"
end function make_farewell
end module farewell_m
16 changes: 16 additions & 0 deletions example_packages/tree_shake/src/greet_m.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
! This module is directly by the executables and
! hence should not be dropped during tree-shaking/pruning
module greet_m
use subdir_constants, only: GREET_STR
implicit none
private

public :: make_greeting
contains
function make_greeting(name) result(greeting)
character(len=*), intent(in) :: name
character(len=:), allocatable :: greeting

greeting = GREET_STR // name // "!"
end function make_greeting
end module greet_m
9 changes: 9 additions & 0 deletions example_packages/tree_shake/src/subdir/constants.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
! This module is used indirectly by the executables
! and hence should not be dropped during tree-shaking/pruning
module subdir_constants
implicit none

character(*), parameter :: GREET_STR = 'Hello, '
character(*), parameter :: FAREWELL_STR = 'Goodbye, '

end module subdir_constants
18 changes: 18 additions & 0 deletions example_packages/tree_shake/test/greet_test.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
program greet_test
use greet_m, only: make_greeting
use iso_fortran_env, only: error_unit, output_unit

implicit none

character(len=:), allocatable :: greeting

allocate(character(len=0) :: greeting)
greeting = make_greeting("World")

if (greeting == "Hello, World!") then
write(output_unit, *) "Passed"
else
write(error_unit, *) "Failed"
call exit(1)
end if
end program greet_test
4 changes: 2 additions & 2 deletions src/fpm.f90
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ subroutine cmd_build(settings)
call fpm_stop(1,'*cmd_build*:model error:'//error%message)
end if

call targets_from_sources(targets, model, error)
call targets_from_sources(targets, model, settings%prune, error)
if (allocated(error)) then
call fpm_stop(1,'*cmd_build*:target error:'//error%message)
end if
Expand Down Expand Up @@ -321,7 +321,7 @@ subroutine cmd_run(settings,test)
call fpm_stop(1, '*cmd_run*:model error:'//error%message)
end if

call targets_from_sources(targets, model, error)
call targets_from_sources(targets, model, settings%prune, error)
if (allocated(error)) then
call fpm_stop(1, '*cmd_run*:targets error:'//error%message)
end if
Expand Down
2 changes: 1 addition & 1 deletion src/fpm/cmd/install.f90
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ subroutine cmd_install(settings)
call build_model(model, settings%fpm_build_settings, package, error)
call handle_error(error)

call targets_from_sources(targets, model, error)
call targets_from_sources(targets, model, settings%prune, error)
call handle_error(error)

installable = (allocated(package%library) .and. package%install%library) &
Expand Down
Loading