mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-16 12:11:04 -06:00
Fortran: Add support for submodule dependencies
Since commit v3.7.0-rc1~73^2~1 (Fortran: Add support for submodule
syntax in dependency scanning, 2016-09-05) we support parsing Fortran
sources that use submodule syntax, but it left addition of `.smod`
dependencies to future work. Add it now.
The syntax
submodule (module_name) submodule_name
means the current source requires `module_name.mod` and provides
`module_name@submodule_name.smod`. The syntax
submodule (module_name:submodule_name) nested_submodule_name
means the current source requires `module_name@submodule_name.smod`
provides `module_name@nested_submodule_name.smod`.
Fixes: #17017
This commit is contained in:
7
Help/release/dev/fortran-submodule-depends.rst
Normal file
7
Help/release/dev/fortran-submodule-depends.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
fortran-submodule-depends
|
||||
-------------------------
|
||||
|
||||
* Fortran dependency scanning now supports dependencies implied by
|
||||
`Fortran Submodules`_.
|
||||
|
||||
.. _`Fortran Submodules`: http://fortranwiki.org/fortran/show/Submodules
|
||||
@@ -1563,7 +1563,7 @@ yyreduce:
|
||||
#line 119 "cmFortranParser.y" /* yacc.c:1646 */
|
||||
{
|
||||
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
|
||||
cmFortranParser_RuleUse(parser, (yyvsp[-4].string));
|
||||
cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string));
|
||||
free((yyvsp[-4].string));
|
||||
free((yyvsp[-2].string));
|
||||
}
|
||||
@@ -1574,7 +1574,7 @@ yyreduce:
|
||||
#line 125 "cmFortranParser.y" /* yacc.c:1646 */
|
||||
{
|
||||
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
|
||||
cmFortranParser_RuleUse(parser, (yyvsp[-6].string));
|
||||
cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string));
|
||||
free((yyvsp[-6].string));
|
||||
free((yyvsp[-4].string));
|
||||
free((yyvsp[-2].string));
|
||||
|
||||
@@ -118,13 +118,13 @@ stmt:
|
||||
}
|
||||
| SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT {
|
||||
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
|
||||
cmFortranParser_RuleUse(parser, $3);
|
||||
cmFortranParser_RuleSubmodule(parser, $3, $5);
|
||||
free($3);
|
||||
free($5);
|
||||
}
|
||||
| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT {
|
||||
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
|
||||
cmFortranParser_RuleUse(parser, $3);
|
||||
cmFortranParser_RuleSubmoduleNested(parser, $3, $5, $7);
|
||||
free($3);
|
||||
free($5);
|
||||
free($7);
|
||||
|
||||
@@ -31,6 +31,8 @@ static void cmFortranModuleAppendUpperLower(std::string const& mod,
|
||||
std::string::size_type ext_len = 0;
|
||||
if (cmHasLiteralSuffix(mod, ".mod")) {
|
||||
ext_len = 4;
|
||||
} else if (cmHasLiteralSuffix(mod, ".smod")) {
|
||||
ext_len = 5;
|
||||
}
|
||||
std::string const& name = mod.substr(0, mod.size() - ext_len);
|
||||
std::string const& ext = mod.substr(mod.size() - ext_len);
|
||||
@@ -283,7 +285,8 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin,
|
||||
if (line[0] == ' ') {
|
||||
if (doing_provides) {
|
||||
std::string mod = line;
|
||||
if (!cmHasLiteralSuffix(mod, ".mod")) {
|
||||
if (!cmHasLiteralSuffix(mod, ".mod") &&
|
||||
!cmHasLiteralSuffix(mod, ".smod")) {
|
||||
// Support fortran.internal files left by older versions of CMake.
|
||||
// They do not include the ".mod" extension.
|
||||
mod += ".mod";
|
||||
@@ -486,7 +489,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
|
||||
if (args.size() >= 5) {
|
||||
compilerId = args[4];
|
||||
}
|
||||
if (!cmHasLiteralSuffix(mod, ".mod")) {
|
||||
if (!cmHasLiteralSuffix(mod, ".mod") && !cmHasLiteralSuffix(mod, ".smod")) {
|
||||
// Support depend.make files left by older versions of CMake.
|
||||
// They do not include the ".mod" extension.
|
||||
mod += ".mod";
|
||||
|
||||
@@ -45,6 +45,13 @@ void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
|
||||
void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name);
|
||||
void cmFortranParser_RuleModule(cmFortranParser* parser,
|
||||
const char* module_name);
|
||||
void cmFortranParser_RuleSubmodule(cmFortranParser* parser,
|
||||
const char* module_name,
|
||||
const char* submodule_name);
|
||||
void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser,
|
||||
const char* module_name,
|
||||
const char* submodule_name,
|
||||
const char* nested_submodule_name);
|
||||
void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* name);
|
||||
void cmFortranParser_RuleUndef(cmFortranParser* parser, const char* name);
|
||||
void cmFortranParser_RuleIfdef(cmFortranParser* parser, const char* name);
|
||||
|
||||
@@ -245,6 +245,50 @@ void cmFortranParser_RuleModule(cmFortranParser* parser,
|
||||
}
|
||||
}
|
||||
|
||||
void cmFortranParser_RuleSubmodule(cmFortranParser* parser,
|
||||
const char* module_name,
|
||||
const char* submodule_name)
|
||||
{
|
||||
if (parser->InPPFalseBranch) {
|
||||
return;
|
||||
}
|
||||
|
||||
// syntax: "submodule (module_name) submodule_name"
|
||||
// requires: "module_name.mod"
|
||||
// provides: "module_name@submodule_name.smod"
|
||||
//
|
||||
// FIXME: Some compilers split the submodule part of a module into a
|
||||
// separate "module_name.smod" file. Whether it is generated or
|
||||
// not depends on conditions more subtle than we currently detect.
|
||||
// For now we depend directly on "module_name.mod".
|
||||
|
||||
std::string const& mod_name = cmSystemTools::LowerCase(module_name);
|
||||
std::string const& sub_name = cmSystemTools::LowerCase(submodule_name);
|
||||
parser->Info.Requires.insert(mod_name + ".mod");
|
||||
parser->Info.Provides.insert(mod_name + "@" + sub_name + ".smod");
|
||||
}
|
||||
|
||||
void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser,
|
||||
const char* module_name,
|
||||
const char* submodule_name,
|
||||
const char* nested_submodule_name)
|
||||
{
|
||||
if (parser->InPPFalseBranch) {
|
||||
return;
|
||||
}
|
||||
|
||||
// syntax: "submodule (module_name:submodule_name) nested_submodule_name"
|
||||
// requires: "module_name@submodule_name.smod"
|
||||
// provides: "module_name@nested_submodule_name.smod"
|
||||
|
||||
std::string const& mod_name = cmSystemTools::LowerCase(module_name);
|
||||
std::string const& sub_name = cmSystemTools::LowerCase(submodule_name);
|
||||
std::string const& nest_name =
|
||||
cmSystemTools::LowerCase(nested_submodule_name);
|
||||
parser->Info.Requires.insert(mod_name + "@" + sub_name + ".smod");
|
||||
parser->Info.Provides.insert(mod_name + "@" + nest_name + ".smod");
|
||||
}
|
||||
|
||||
void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* macro)
|
||||
{
|
||||
if (!parser->InPPFalseBranch) {
|
||||
|
||||
@@ -1 +1,20 @@
|
||||
add_executable(submod main.f90 provide.f90)
|
||||
# The program units in this file consist of a module/submodule
|
||||
# tree represented by the following graph:
|
||||
#
|
||||
# parent
|
||||
# |
|
||||
# / \
|
||||
# / \
|
||||
# child sibling
|
||||
# |
|
||||
# grandchild
|
||||
#
|
||||
# where the parent node is a module and all other nodes are submodules.
|
||||
|
||||
add_executable(submod
|
||||
main.f90
|
||||
parent.f90
|
||||
child.f90
|
||||
grandchild.f90
|
||||
sibling.f90
|
||||
)
|
||||
|
||||
10
Tests/FortranModules/Submodules/child.f90
Normal file
10
Tests/FortranModules/Submodules/child.f90
Normal file
@@ -0,0 +1,10 @@
|
||||
! Test the notation for a 1st-generation direct
|
||||
! descendant of a parent module
|
||||
submodule ( parent ) child
|
||||
implicit none
|
||||
contains
|
||||
module function child_function() result(child_stuff)
|
||||
logical :: child_stuff
|
||||
child_stuff=.true.
|
||||
end function
|
||||
end submodule child
|
||||
8
Tests/FortranModules/Submodules/grandchild.f90
Normal file
8
Tests/FortranModules/Submodules/grandchild.f90
Normal file
@@ -0,0 +1,8 @@
|
||||
! Test the notation for an Nth-generation descendant
|
||||
! for N>1, which necessitates the colon.
|
||||
submodule ( parent : child ) grandchild
|
||||
contains
|
||||
module subroutine grandchild_subroutine()
|
||||
print *,"Test passed."
|
||||
end subroutine
|
||||
end submodule grandchild
|
||||
17
Tests/FortranModules/Submodules/parent.f90
Normal file
17
Tests/FortranModules/Submodules/parent.f90
Normal file
@@ -0,0 +1,17 @@
|
||||
module parent
|
||||
implicit none
|
||||
|
||||
interface
|
||||
|
||||
! Test Fortran 2008 "module function" syntax
|
||||
module function child_function() result(child_stuff)
|
||||
logical :: child_stuff
|
||||
end function
|
||||
|
||||
! Test Fortran 2008 "module subroutine" syntax
|
||||
module subroutine grandchild_subroutine()
|
||||
end subroutine
|
||||
|
||||
end interface
|
||||
|
||||
end module parent
|
||||
@@ -1,57 +0,0 @@
|
||||
! The program units in this file consist of a
|
||||
! module/submodule tree represented by the following
|
||||
! graph:
|
||||
!
|
||||
! parent
|
||||
! |
|
||||
! / \
|
||||
! / \
|
||||
! child sibling
|
||||
! |
|
||||
! grandchild
|
||||
!
|
||||
! where the parent node is a module and all other
|
||||
! nodes are submodules.
|
||||
|
||||
module parent
|
||||
implicit none
|
||||
|
||||
interface
|
||||
|
||||
! Test Fortran 2008 "module function" syntax
|
||||
module function child_function() result(child_stuff)
|
||||
logical :: child_stuff
|
||||
end function
|
||||
|
||||
! Test Fortran 2008 "module subroutine" syntax
|
||||
module subroutine grandchild_subroutine()
|
||||
end subroutine
|
||||
|
||||
end interface
|
||||
|
||||
end module parent
|
||||
|
||||
! Test the notation for a 1st-generation direct
|
||||
! descendant of a parent module
|
||||
submodule ( parent ) child
|
||||
implicit none
|
||||
contains
|
||||
module function child_function() result(child_stuff)
|
||||
logical :: child_stuff
|
||||
child_stuff=.true.
|
||||
end function
|
||||
end submodule child
|
||||
|
||||
! Empty submodule for checking disambiguation of
|
||||
! nodes at the same vertical level in the tree
|
||||
submodule ( parent ) sibling
|
||||
end submodule sibling
|
||||
|
||||
! Test the notation for an Nth-generation descendant
|
||||
! for N>1, which necessitates the colon.
|
||||
submodule ( parent : child ) grandchild
|
||||
contains
|
||||
module subroutine grandchild_subroutine()
|
||||
print *,"Test passed."
|
||||
end subroutine
|
||||
end submodule grandchild
|
||||
4
Tests/FortranModules/Submodules/sibling.f90
Normal file
4
Tests/FortranModules/Submodules/sibling.f90
Normal file
@@ -0,0 +1,4 @@
|
||||
! Empty submodule for checking disambiguation of
|
||||
! nodes at the same vertical level in the tree
|
||||
submodule ( parent ) sibling
|
||||
end submodule sibling
|
||||
Reference in New Issue
Block a user