summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2018-04-23 14:28:40 (GMT)
committerKitware Robot <kwrobot@kitware.com>2018-04-23 14:28:50 (GMT)
commitf9b3b5a7730e1c8b87742bcff516acaed7fa7882 (patch)
tree6c43518823ecf60015beb7050baaa984c3e746aa
parent97ecefa73b54b7c585e2e16cee844b943ccf062f (diff)
parentb1f95e5b1477794c0ee3a56a4ea016a34c3e3d5c (diff)
downloadCMake-f9b3b5a7730e1c8b87742bcff516acaed7fa7882.zip
CMake-f9b3b5a7730e1c8b87742bcff516acaed7fa7882.tar.gz
CMake-f9b3b5a7730e1c8b87742bcff516acaed7fa7882.tar.bz2
Merge topic 'fortran-submodule-depends'
b1f95e5b14 Fortran: Extend submodule test with great-grandchild 402735314e Fortran: Add support for submodule dependencies 62538b2c4c Fortran: Refactor to treat .mod extension as part of module name Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Izaak Beekman <contact@izaakbeekman.com> Merge-request: !1989
-rw-r--r--Help/release/dev/fortran-submodule-depends.rst7
-rw-r--r--Source/LexerParser/cmFortranParser.cxx4
-rw-r--r--Source/LexerParser/cmFortranParser.y4
-rw-r--r--Source/cmDependsFortran.cxx59
-rw-r--r--Source/cmFortranParser.h12
-rw-r--r--Source/cmFortranParserImpl.cxx69
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx2
-rw-r--r--Tests/FortranModules/Submodules/CMakeLists.txt24
-rw-r--r--Tests/FortranModules/Submodules/child.f9010
-rw-r--r--Tests/FortranModules/Submodules/grandchild.f908
-rw-r--r--Tests/FortranModules/Submodules/greatgrandchild.f908
-rw-r--r--Tests/FortranModules/Submodules/main.f902
-rw-r--r--Tests/FortranModules/Submodules/parent.f9022
-rw-r--r--Tests/FortranModules/Submodules/provide.f9057
-rw-r--r--Tests/FortranModules/Submodules/sibling.f909
15 files changed, 207 insertions, 90 deletions
diff --git a/Help/release/dev/fortran-submodule-depends.rst b/Help/release/dev/fortran-submodule-depends.rst
new file mode 100644
index 0000000..b795a84
--- /dev/null
+++ b/Help/release/dev/fortran-submodule-depends.rst
@@ -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
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index 2b3452f..00c8a8a 100644
--- a/Source/LexerParser/cmFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -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));
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
index acfb40a..5e09248 100644
--- a/Source/LexerParser/cmFortranParser.y
+++ b/Source/LexerParser/cmFortranParser.y
@@ -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);
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 1a66ca0..dbea15a 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -10,6 +10,7 @@
#include <string.h>
#include <utility>
+#include "cmAlgorithms.h"
#include "cmFortranParser.h" /* Interface to parser object. */
#include "cmGeneratedFileStream.h"
#include "cmLocalGenerator.h"
@@ -23,6 +24,22 @@
// use lower case and some always use upper case. I do not know if any
// use the case from the source code.
+static void cmFortranModuleAppendUpperLower(std::string const& mod,
+ std::string& mod_upper,
+ std::string& mod_lower)
+{
+ 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);
+ mod_upper += cmSystemTools::UpperCase(name) + ext;
+ mod_lower += mod;
+}
+
class cmDependsFortranInternals
{
public:
@@ -181,16 +198,13 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
for (std::string const& i : provides) {
std::string mod_upper = mod_dir;
mod_upper += "/";
- mod_upper += cmSystemTools::UpperCase(i);
- mod_upper += ".mod";
std::string mod_lower = mod_dir;
mod_lower += "/";
- mod_lower += i;
- mod_lower += ".mod";
+ cmFortranModuleAppendUpperLower(i, mod_upper, mod_lower);
std::string stamp = stamp_dir;
stamp += "/";
stamp += i;
- stamp += ".mod.stamp";
+ stamp += ".stamp";
fcStream << "\n";
fcStream << " \""
<< this->MaybeConvertToRelativePath(currentBinDir, mod_lower)
@@ -270,7 +284,14 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin,
if (line[0] == ' ') {
if (doing_provides) {
- this->ConsiderModule(line.c_str() + 1, stampDir);
+ std::string mod = line;
+ 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";
+ }
+ this->ConsiderModule(mod.c_str() + 1, stampDir);
}
} else if (line == "provides") {
doing_provides = true;
@@ -292,7 +313,7 @@ void cmDependsFortran::ConsiderModule(const char* name, const char* stampDir)
std::string stampFile = stampDir;
stampFile += "/";
stampFile += name;
- stampFile += ".mod.stamp";
+ stampFile += ".stamp";
required->second = stampFile;
}
}
@@ -366,7 +387,6 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
// Always use lower case for the mod stamp file name. The
// cmake_copy_f90_mod will call back to this class, which will
// try various cases for the real mod file name.
- std::string m = cmSystemTools::LowerCase(i);
std::string modFile = mod_dir;
modFile += "/";
modFile += i;
@@ -375,8 +395,8 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
cmOutputConverter::SHELL);
std::string stampFile = stamp_dir;
stampFile += "/";
- stampFile += m;
- stampFile += ".mod.stamp";
+ stampFile += i;
+ stampFile += ".stamp";
stampFile = this->MaybeConvertToRelativePath(binDir, stampFile);
std::string const stampFileForShell =
this->LocalGenerator->ConvertToOutputFormat(stampFile,
@@ -423,10 +443,9 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
bool cmDependsFortran::FindModule(std::string const& name, std::string& module)
{
// Construct possible names for the module file.
- std::string mod_upper = cmSystemTools::UpperCase(name);
- std::string mod_lower = name;
- mod_upper += ".mod";
- mod_lower += ".mod";
+ std::string mod_upper;
+ std::string mod_lower;
+ cmFortranModuleAppendUpperLower(name, mod_upper, mod_lower);
// Search the include path for the module.
std::string fullName;
@@ -470,17 +489,19 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
if (args.size() >= 5) {
compilerId = args[4];
}
+ 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";
+ }
std::string mod_dir = cmSystemTools::GetFilenamePath(mod);
if (!mod_dir.empty()) {
mod_dir += "/";
}
std::string mod_upper = mod_dir;
- mod_upper += cmSystemTools::UpperCase(cmSystemTools::GetFilenameName(mod));
std::string mod_lower = mod_dir;
- mod_lower += cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(mod));
- mod += ".mod";
- mod_upper += ".mod";
- mod_lower += ".mod";
+ cmFortranModuleAppendUpperLower(cmSystemTools::GetFilenameName(mod),
+ mod_upper, mod_lower);
if (cmSystemTools::FileExists(mod_upper, true)) {
if (cmDependsFortran::ModulesDiffer(mod_upper.c_str(), stamp.c_str(),
compilerId.c_str())) {
diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h
index 3f5ad87..efcd100 100644
--- a/Source/cmFortranParser.h
+++ b/Source/cmFortranParser.h
@@ -39,11 +39,19 @@ int cmFortranParser_GetOldStartcond(cmFortranParser* parser);
/* Callbacks for parser. */
void cmFortranParser_Error(cmFortranParser* parser, const char* message);
-void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name);
+void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name);
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename);
void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name);
-void cmFortranParser_RuleModule(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);
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
index dd4f16b..01cbb78 100644
--- a/Source/cmFortranParserImpl.cxx
+++ b/Source/cmFortranParserImpl.cxx
@@ -168,11 +168,16 @@ void cmFortranParser_Error(cmFortranParser* parser, const char* msg)
parser->Error = msg ? msg : "unknown error";
}
-void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name)
+void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name)
{
- if (!parser->InPPFalseBranch) {
- parser->Info.Requires.insert(cmSystemTools::LowerCase(name));
+ if (parser->InPPFalseBranch) {
+ return;
}
+
+ // syntax: "use module_name"
+ // requires: "module_name.mod"
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ parser->Info.Requires.insert(mod_name + ".mod");
}
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
@@ -225,11 +230,63 @@ void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name)
}
}
-void cmFortranParser_RuleModule(cmFortranParser* parser, const char* name)
+void cmFortranParser_RuleModule(cmFortranParser* parser,
+ const char* module_name)
{
- if (!parser->InPPFalseBranch && !parser->InInterface) {
- parser->Info.Provides.insert(cmSystemTools::LowerCase(name));
+ if (parser->InPPFalseBranch) {
+ return;
}
+
+ if (!parser->InInterface) {
+ // syntax: "module module_name"
+ // provides: "module_name.mod"
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ parser->Info.Provides.insert(mod_name + ".mod");
+ }
+}
+
+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)
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 599e27c..2a8576f 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1812,7 +1812,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
Json::Value tm = Json::objectValue;
for (cmFortranObjectInfo const& object : objects) {
for (std::string const& p : object.Provides) {
- std::string const mod = module_dir + p + ".mod";
+ std::string const mod = module_dir + p;
mod_files[p] = mod;
tm[p] = mod;
}
diff --git a/Tests/FortranModules/Submodules/CMakeLists.txt b/Tests/FortranModules/Submodules/CMakeLists.txt
index bf0152f..ab8e0f9 100644
--- a/Tests/FortranModules/Submodules/CMakeLists.txt
+++ b/Tests/FortranModules/Submodules/CMakeLists.txt
@@ -1 +1,23 @@
-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
+# |
+# GreatGrandChild
+#
+# where the parent node is a module and all other nodes are submodules.
+
+add_executable(submod
+ main.f90
+ parent.f90
+ child.f90
+ grandchild.f90
+ greatgrandchild.f90
+ sibling.f90
+ )
diff --git a/Tests/FortranModules/Submodules/child.f90 b/Tests/FortranModules/Submodules/child.f90
new file mode 100644
index 0000000..838ab61
--- /dev/null
+++ b/Tests/FortranModules/Submodules/child.f90
@@ -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
diff --git a/Tests/FortranModules/Submodules/grandchild.f90 b/Tests/FortranModules/Submodules/grandchild.f90
new file mode 100644
index 0000000..1aef63e
--- /dev/null
+++ b/Tests/FortranModules/Submodules/grandchild.f90
@@ -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
diff --git a/Tests/FortranModules/Submodules/greatgrandchild.f90 b/Tests/FortranModules/Submodules/greatgrandchild.f90
new file mode 100644
index 0000000..85404ea
--- /dev/null
+++ b/Tests/FortranModules/Submodules/greatgrandchild.f90
@@ -0,0 +1,8 @@
+! Test the notation for an Nth-generation descendant
+! for N>1, which necessitates the colon.
+submodule ( parent : grandchild ) GreatGrandChild
+contains
+ module subroutine GreatGrandChild_subroutine()
+ print *,"Test passed."
+ end subroutine
+end submodule GreatGrandChild
diff --git a/Tests/FortranModules/Submodules/main.f90 b/Tests/FortranModules/Submodules/main.f90
index 3c750ce..3cd2989 100644
--- a/Tests/FortranModules/Submodules/main.f90
+++ b/Tests/FortranModules/Submodules/main.f90
@@ -1,5 +1,7 @@
program main
use parent, only : child_function,grandchild_subroutine
+ use parent, only : sibling_function,GreatGrandChild_subroutine
implicit none
if (child_function()) call grandchild_subroutine
+ if (sibling_function()) call GreatGrandChild_subroutine
end program
diff --git a/Tests/FortranModules/Submodules/parent.f90 b/Tests/FortranModules/Submodules/parent.f90
new file mode 100644
index 0000000..3180b70
--- /dev/null
+++ b/Tests/FortranModules/Submodules/parent.f90
@@ -0,0 +1,22 @@
+module parent
+ implicit none
+
+ interface
+
+ ! Test Fortran 2008 "module function" syntax
+ module function child_function() result(child_stuff)
+ logical :: child_stuff
+ end function
+ module function sibling_function() result(sibling_stuff)
+ logical :: sibling_stuff
+ end function
+
+ ! Test Fortran 2008 "module subroutine" syntax
+ module subroutine grandchild_subroutine()
+ end subroutine
+ module subroutine GreatGrandChild_subroutine()
+ end subroutine
+
+ end interface
+
+end module parent
diff --git a/Tests/FortranModules/Submodules/provide.f90 b/Tests/FortranModules/Submodules/provide.f90
deleted file mode 100644
index 0ad216a..0000000
--- a/Tests/FortranModules/Submodules/provide.f90
+++ /dev/null
@@ -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
diff --git a/Tests/FortranModules/Submodules/sibling.f90 b/Tests/FortranModules/Submodules/sibling.f90
new file mode 100644
index 0000000..8c0943d
--- /dev/null
+++ b/Tests/FortranModules/Submodules/sibling.f90
@@ -0,0 +1,9 @@
+! Empty submodule for checking disambiguation of
+! nodes at the same vertical level in the tree
+submodule ( parent ) sibling
+contains
+ module function sibling_function() result(sibling_stuff)
+ logical :: sibling_stuff
+ sibling_stuff=.true.
+ end function
+end submodule sibling