ENH: Implement Fortran module dependencies across targets and directories.
- See issue #5809 - Keep information about all sources in the target until deps are written - Create a fortran.internal file after scanning that lists modules provided - Load fortran.internal files from linked targets to find modules - Search the include path for external modules - Create file-level deps on in-project module timestamps or external mods
This commit is contained in:
parent
42f3f3c342
commit
68dad94b00
|
@ -75,6 +75,13 @@ bool cmDepends::Write(std::ostream &makeDepends,
|
|||
}
|
||||
}
|
||||
|
||||
return this->Finalize(makeDepends, internalDepends);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmDepends::Finalize(std::ostream&,
|
||||
std::ostream&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,10 @@ protected:
|
|||
// otherwise.
|
||||
virtual bool CheckDependencies(std::istream& internalDepends);
|
||||
|
||||
// Finalize the dependency information for the target.
|
||||
virtual bool Finalize(std::ostream& makeDepends,
|
||||
std::ostream& internalDepends);
|
||||
|
||||
// The directory in which the build rule for the target file is executed.
|
||||
std::string CompileDirectory;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "cmSystemTools.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
|
||||
#include "cmDependsFortranParser.h" /* Interface to parser object. */
|
||||
|
||||
|
@ -29,6 +30,22 @@
|
|||
// use lower case and some always use upper case. I do not know if any
|
||||
// use the case from the source code.
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Information about a single source file.
|
||||
class cmDependsFortranSourceInfo
|
||||
{
|
||||
public:
|
||||
// The name of the soruce file.
|
||||
std::string Source;
|
||||
|
||||
// Set of provided and required modules.
|
||||
std::set<cmStdString> Provides;
|
||||
std::set<cmStdString> Requires;
|
||||
|
||||
// Set of files included in the translation unit.
|
||||
std::set<cmStdString> Includes;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Parser methods not included in generated interface.
|
||||
|
||||
|
@ -52,7 +69,8 @@ struct cmDependsFortranFile
|
|||
|
||||
struct cmDependsFortranParser_s
|
||||
{
|
||||
cmDependsFortranParser_s(cmDependsFortran* self);
|
||||
cmDependsFortranParser_s(cmDependsFortran* self,
|
||||
cmDependsFortranSourceInfo& info);
|
||||
~cmDependsFortranParser_s();
|
||||
|
||||
// Pointer back to the main class.
|
||||
|
@ -75,29 +93,57 @@ struct cmDependsFortranParser_s
|
|||
std::vector<bool> SkipToEnd;
|
||||
int StepI;
|
||||
|
||||
// Set of provided and required modules.
|
||||
std::set<cmStdString> Provides;
|
||||
std::set<cmStdString> Requires;
|
||||
// Information about the parsed source.
|
||||
cmDependsFortranSourceInfo& Info;
|
||||
};
|
||||
|
||||
// Set of files included in the translation unit.
|
||||
std::set<cmStdString> Includes;
|
||||
//----------------------------------------------------------------------------
|
||||
class cmDependsFortranInternals
|
||||
{
|
||||
public:
|
||||
// The set of modules provided by this target.
|
||||
std::set<cmStdString> TargetProvides;
|
||||
|
||||
// Map modules required by this target to locations.
|
||||
typedef std::map<cmStdString, cmStdString> TargetRequiresMap;
|
||||
TargetRequiresMap TargetRequires;
|
||||
|
||||
// Information about each object file.
|
||||
typedef std::map<cmStdString, cmDependsFortranSourceInfo> ObjectInfoMap;
|
||||
ObjectInfoMap ObjectInfo;
|
||||
|
||||
cmDependsFortranSourceInfo& CreateObjectInfo(const char* obj,
|
||||
const char* src)
|
||||
{
|
||||
std::map<cmStdString, cmDependsFortranSourceInfo>::iterator i =
|
||||
this->ObjectInfo.find(obj);
|
||||
if(i == this->ObjectInfo.end())
|
||||
{
|
||||
std::map<cmStdString, cmDependsFortranSourceInfo>::value_type
|
||||
entry(obj, cmDependsFortranSourceInfo());
|
||||
i = this->ObjectInfo.insert(entry).first;
|
||||
i->second.Source = src;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmDependsFortran::cmDependsFortran():
|
||||
IncludePath(0)
|
||||
IncludePath(0), Internal(0)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmDependsFortran::cmDependsFortran(std::vector<std::string> const& includes):
|
||||
IncludePath(&includes)
|
||||
IncludePath(&includes), Internal(new cmDependsFortranInternals)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmDependsFortran::~cmDependsFortran()
|
||||
{
|
||||
delete this->Internal;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -121,12 +167,12 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
|
|||
return false;
|
||||
}
|
||||
|
||||
// Get the directory in which stamp files will be stored.
|
||||
std::string mod_dir =
|
||||
this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
|
||||
// Get the information object for this source.
|
||||
cmDependsFortranSourceInfo& info =
|
||||
this->Internal->CreateObjectInfo(obj, src);
|
||||
|
||||
// Create the parser object.
|
||||
cmDependsFortranParser parser(this);
|
||||
cmDependsFortranParser parser(this, info);
|
||||
|
||||
// Push on the starting file.
|
||||
cmDependsFortranParser_FilePush(&parser, src);
|
||||
|
@ -138,11 +184,189 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmDependsFortran::Finalize(std::ostream& makeDepends,
|
||||
std::ostream& internalDepends)
|
||||
{
|
||||
// Prepare the module search process.
|
||||
this->LocateModules();
|
||||
|
||||
// Actually write dependencies to the streams.
|
||||
typedef cmDependsFortranInternals::ObjectInfoMap ObjectInfoMap;
|
||||
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
|
||||
for(ObjectInfoMap::const_iterator i = objInfo.begin();
|
||||
i != objInfo.end(); ++i)
|
||||
{
|
||||
if(!this->WriteDependenciesReal(i->first.c_str(), i->second,
|
||||
makeDepends, internalDepends))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the list of modules provided by this target.
|
||||
std::string fiName = this->TargetDirectory;
|
||||
fiName += "/fortran.internal";
|
||||
cmGeneratedFileStream fiStream(fiName.c_str());
|
||||
fiStream << "# The fortran modules provided by this target.\n";
|
||||
fiStream << "provides\n";
|
||||
std::set<cmStdString> const& provides = this->Internal->TargetProvides;
|
||||
for(std::set<cmStdString>::const_iterator i = provides.begin();
|
||||
i != provides.end(); ++i)
|
||||
{
|
||||
fiStream << " " << *i << "\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmDependsFortran::LocateModules()
|
||||
{
|
||||
// Collect the set of modules provided and required by all sources.
|
||||
typedef cmDependsFortranInternals::ObjectInfoMap ObjectInfoMap;
|
||||
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
|
||||
for(ObjectInfoMap::const_iterator infoI = objInfo.begin();
|
||||
infoI != objInfo.end(); ++infoI)
|
||||
{
|
||||
cmDependsFortranSourceInfo const& info = infoI->second;
|
||||
for(std::set<cmStdString>::const_iterator i = info.Provides.begin();
|
||||
i != info.Provides.end(); ++i)
|
||||
{
|
||||
// Include this module in the set provided by this target.
|
||||
this->Internal->TargetProvides.insert(*i);
|
||||
}
|
||||
|
||||
for(std::set<cmStdString>::const_iterator i = info.Requires.begin();
|
||||
i != info.Requires.end(); ++i)
|
||||
{
|
||||
// Include this module in the set required by this target.
|
||||
this->Internal->TargetRequires[*i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Short-circuit for simple targets.
|
||||
if(this->Internal->TargetRequires.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Match modules provided by this target to those it requires.
|
||||
this->MatchLocalModules();
|
||||
|
||||
// Load information about other targets.
|
||||
cmMakefile* mf = this->LocalGenerator->GetMakefile();
|
||||
std::vector<std::string> infoFiles;
|
||||
if(const char* infoFilesValue =
|
||||
mf->GetDefinition("CMAKE_TARGET_LINKED_INFO_FILES"))
|
||||
{
|
||||
cmSystemTools::ExpandListArgument(infoFilesValue, infoFiles);
|
||||
}
|
||||
for(std::vector<std::string>::const_iterator i = infoFiles.begin();
|
||||
i != infoFiles.end(); ++i)
|
||||
{
|
||||
std::string targetDir = cmSystemTools::GetFilenamePath(*i);
|
||||
std::string fname = targetDir + "/fortran.internal";
|
||||
std::ifstream fin(fname.c_str());
|
||||
if(fin)
|
||||
{
|
||||
std::string moduleDir =
|
||||
cmSystemTools::GetFilenamePath(
|
||||
cmSystemTools::GetFilenamePath(targetDir));
|
||||
this->MatchRemoteModules(fin, moduleDir.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmDependsFortran::MatchLocalModules()
|
||||
{
|
||||
const char* moduleDir =
|
||||
this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
|
||||
std::set<cmStdString> const& provides = this->Internal->TargetProvides;
|
||||
for(std::set<cmStdString>::const_iterator i = provides.begin();
|
||||
i != provides.end(); ++i)
|
||||
{
|
||||
this->ConsiderModule(i->c_str(), moduleDir);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmDependsFortran::MatchRemoteModules(std::istream& fin,
|
||||
const char* moduleDir)
|
||||
{
|
||||
std::string line;
|
||||
bool doing_provides;
|
||||
while(cmSystemTools::GetLineFromStream(fin, line))
|
||||
{
|
||||
// Ignore comments and empty lines.
|
||||
if(line.empty() || line[0] == '#' || line[0] == '\r')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(line[0] == ' ')
|
||||
{
|
||||
if(doing_provides)
|
||||
{
|
||||
this->ConsiderModule(line.c_str()+1, moduleDir);
|
||||
}
|
||||
}
|
||||
else if(line == "provides")
|
||||
{
|
||||
doing_provides = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
doing_provides = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmDependsFortran::ConsiderModule(const char* name,
|
||||
const char* moduleDir)
|
||||
{
|
||||
// Locate each required module.
|
||||
typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap;
|
||||
TargetRequiresMap::iterator required =
|
||||
this->Internal->TargetRequires.find(name);
|
||||
if(required != this->Internal->TargetRequires.end() &&
|
||||
required->second.empty())
|
||||
{
|
||||
// The module is provided by a CMake target. It will have a stamp file.
|
||||
std::string stampFile = moduleDir;
|
||||
stampFile += "/";
|
||||
stampFile += name;
|
||||
stampFile += ".mod.stamp";
|
||||
required->second = stampFile;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
cmDependsFortran
|
||||
::WriteDependenciesReal(const char *obj,
|
||||
cmDependsFortranSourceInfo const& info,
|
||||
std::ostream& makeDepends,
|
||||
std::ostream& internalDepends)
|
||||
{
|
||||
typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap;
|
||||
|
||||
// Get the source file for this object.
|
||||
const char* src = info.Source.c_str();
|
||||
|
||||
// Get the directory in which stamp files will be stored.
|
||||
std::string mod_dir =
|
||||
this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
|
||||
|
||||
// Write the include dependencies to the output stream.
|
||||
internalDepends << obj << std::endl;
|
||||
internalDepends << " " << src << std::endl;
|
||||
for(std::set<cmStdString>::const_iterator i = parser.Includes.begin();
|
||||
i != parser.Includes.end(); ++i)
|
||||
for(std::set<cmStdString>::const_iterator i = info.Includes.begin();
|
||||
i != info.Includes.end(); ++i)
|
||||
{
|
||||
makeDepends << obj << ": "
|
||||
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
|
||||
|
@ -152,12 +376,23 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
|
|||
makeDepends << std::endl;
|
||||
|
||||
// Write module requirements to the output stream.
|
||||
for(std::set<cmStdString>::const_iterator i = parser.Requires.begin();
|
||||
i != parser.Requires.end(); ++i)
|
||||
for(std::set<cmStdString>::const_iterator i = info.Requires.begin();
|
||||
i != info.Requires.end(); ++i)
|
||||
{
|
||||
// Require only modules not provided in the same source.
|
||||
if(parser.Provides.find(*i) == parser.Provides.end())
|
||||
if(info.Provides.find(*i) != info.Provides.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the module is provided in this target special handling is
|
||||
// needed.
|
||||
if(this->Internal->TargetProvides.find(*i) !=
|
||||
this->Internal->TargetProvides.end())
|
||||
{
|
||||
// The module is provided by a different source in the same
|
||||
// target. Add the proxy dependency to make sure the other
|
||||
// source builds first.
|
||||
std::string proxy = mod_dir;
|
||||
proxy += "/";
|
||||
proxy += *i;
|
||||
|
@ -171,54 +406,41 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
|
|||
|
||||
// create an empty proxy in case no other source provides it
|
||||
makeDepends << proxy << ":" << std::endl;
|
||||
}
|
||||
|
||||
// The object file should depend on timestamped files for the
|
||||
// modules it uses.
|
||||
std::string m = cmSystemTools::LowerCase(*i);
|
||||
std::string stampFile = mod_dir;
|
||||
stampFile += "/";
|
||||
stampFile += m;
|
||||
stampFile += ".mod.stamp";
|
||||
stampFile =
|
||||
this->LocalGenerator->Convert(stampFile.c_str(),
|
||||
TargetRequiresMap::const_iterator required =
|
||||
this->Internal->TargetRequires.find(*i);
|
||||
if(required == this->Internal->TargetRequires.end()) { abort(); }
|
||||
if(!required->second.empty())
|
||||
{
|
||||
// This module is known. Depend on its timestamp file.
|
||||
std::string stampFile =
|
||||
this->LocalGenerator->Convert(required->second.c_str(),
|
||||
cmLocalGenerator::HOME_OUTPUT,
|
||||
cmLocalGenerator::SHELL);
|
||||
makeDepends << obj << ": " << stampFile << "\n";
|
||||
|
||||
// Create a dummy timestamp file for the module.
|
||||
std::string fullPath = mod_dir;
|
||||
fullPath += "/";
|
||||
fullPath += m;
|
||||
fullPath += ".mod.stamp";
|
||||
if(!cmSystemTools::FileExists(fullPath.c_str(), true))
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ofstream dummy(fullPath.c_str());
|
||||
dummy
|
||||
<< "This is a fake module timestamp file created by CMake because\n"
|
||||
<< " " << src << "\n"
|
||||
<< "requires the module and\n"
|
||||
<< " " << obj << "\n"
|
||||
<< "depends on this timestamp file.\n"
|
||||
<< "\n"
|
||||
<< "If another source in the same directory provides the module\n"
|
||||
<< "this file will be overwritten with a real module timestamp\n"
|
||||
<< "that is updated when the module is rebuilt.\n"
|
||||
<< "\n"
|
||||
<< "If no source in the directory provides the module at least\n"
|
||||
<< "the project will build without failing to find the module\n"
|
||||
<< "timestamp.\n"
|
||||
<< "\n"
|
||||
<< "In the future CMake may be able to locate modules in other\n"
|
||||
<< "directories or outside the project and update this timestamp\n"
|
||||
<< "file as necessary.\n"
|
||||
;
|
||||
// This module is not known to CMake. Try to locate it where
|
||||
// the compiler will and depend on that.
|
||||
std::string module;
|
||||
if(this->FindModule(*i, module))
|
||||
{
|
||||
module =
|
||||
this->LocalGenerator->Convert(module.c_str(),
|
||||
cmLocalGenerator::HOME_OUTPUT,
|
||||
cmLocalGenerator::SHELL);
|
||||
makeDepends << obj << ": " << module << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write provided modules to the output stream.
|
||||
for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
|
||||
i != parser.Provides.end(); ++i)
|
||||
for(std::set<cmStdString>::const_iterator i = info.Provides.begin();
|
||||
i != info.Provides.end(); ++i)
|
||||
{
|
||||
std::string proxy = mod_dir;
|
||||
proxy += "/";
|
||||
|
@ -231,14 +453,17 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
|
|||
}
|
||||
|
||||
// If any modules are provided then they must be converted to stamp files.
|
||||
if(!parser.Provides.empty())
|
||||
if(!info.Provides.empty())
|
||||
{
|
||||
// Create a target to copy the module after the object file
|
||||
// changes.
|
||||
makeDepends << obj << ".provides.build:\n";
|
||||
for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
|
||||
i != parser.Provides.end(); ++i)
|
||||
for(std::set<cmStdString>::const_iterator i = info.Provides.begin();
|
||||
i != info.Provides.end(); ++i)
|
||||
{
|
||||
// Include this module in the set provided by this target.
|
||||
this->Internal->TargetProvides.insert(*i);
|
||||
|
||||
// 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.
|
||||
|
@ -276,63 +501,47 @@ bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
|
|||
makeDepends << driver << ": " << obj << ".provides.build\n";
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO:
|
||||
What about .mod files provided in another directory and found with a
|
||||
-M search path? The stamp file will not be updated, so things might
|
||||
not rebuild. Possible solutions (not all thought through):
|
||||
|
||||
Solution 1: Have all the .o.requires in a directory depend on a
|
||||
single .outside.requires that searches for .mod files in another
|
||||
directory of the build tree and uses copy-if-different to produce
|
||||
the local directory's stamp files. (won't work because the single
|
||||
rule cannot know about the modules)
|
||||
|
||||
Solution 2: When the dependency is detected search the module
|
||||
include path for a mark file indicating the module is provided. If
|
||||
not found just write the dummy stamp file. If found, we need a rule
|
||||
to copy-if-different the module file. When a module is provided,
|
||||
write this mark file.
|
||||
|
||||
Solution 3: Use a set of make rules like this:
|
||||
|
||||
# When required:
|
||||
foo.mod.proxy: foo.mod.default
|
||||
foo.mod.default:: foo.mod.hack
|
||||
@echo foo.mod.default2 # Search for and copy-if-different the mod file.
|
||||
foo.mod.hack:
|
||||
|
||||
# When provided:
|
||||
foo.mod.proxy: foo.o.requires
|
||||
@rm -f foo.mod.hack foo.mod.default
|
||||
foo.o.requires: foo.mod.hack
|
||||
@echo foo.o.requires
|
||||
foo.mod.hack:
|
||||
@touch foo.mod.hack
|
||||
@touch foo.mod.default
|
||||
|
||||
Solution 4:
|
||||
|
||||
When scanning dependencies and providing a module:
|
||||
- Create a .mod.provided.
|
||||
- Add .mod.proxy rule depending on corresponding .o.requires.
|
||||
|
||||
When scanning dependencies and requiring a module:
|
||||
- Search the module path for a .mod.provided or a .mod.
|
||||
- If a .mod.provided is found depend on the corresponding .mod.stamp
|
||||
(it is provided by CMake in another directory)
|
||||
- Else, if a .mod is found depend on it directly
|
||||
(it is provided in another directory by a non-CMake project)
|
||||
- Else:
|
||||
- Add the empty proxy rule (if it is provided locally this will hook it)
|
||||
- Depend on a local .mod.stamp (it might be provided locally)
|
||||
- Create the dummy local .mod.stamp (it might not be provided locally)
|
||||
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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";
|
||||
|
||||
// Search the include path for the module.
|
||||
std::string fullName;
|
||||
for(std::vector<std::string>::const_iterator i =
|
||||
this->IncludePath->begin(); i != this->IncludePath->end(); ++i)
|
||||
{
|
||||
// Try the lower-case name.
|
||||
fullName = *i;
|
||||
fullName += "/";
|
||||
fullName += mod_lower;
|
||||
if(cmSystemTools::FileExists(fullName.c_str(), true))
|
||||
{
|
||||
module = fullName;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try the upper-case name.
|
||||
fullName = *i;
|
||||
fullName += "/";
|
||||
fullName += mod_upper;
|
||||
if(cmSystemTools::FileExists(fullName.c_str(), true))
|
||||
{
|
||||
module = fullName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
|
||||
{
|
||||
|
@ -427,8 +636,10 @@ bool cmDependsFortran::FindIncludeFile(const char* dir,
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmDependsFortranParser_s::cmDependsFortranParser_s(cmDependsFortran* self):
|
||||
Self(self)
|
||||
cmDependsFortranParser_s
|
||||
::cmDependsFortranParser_s(cmDependsFortran* self,
|
||||
cmDependsFortranSourceInfo& info):
|
||||
Self(self), Info(info)
|
||||
{
|
||||
this->InInterface = 0;
|
||||
|
||||
|
@ -565,7 +776,7 @@ void cmDependsFortranParser_Error(cmDependsFortranParser*, const char*)
|
|||
void cmDependsFortranParser_RuleUse(cmDependsFortranParser* parser,
|
||||
const char* name)
|
||||
{
|
||||
parser->Requires.insert(cmSystemTools::LowerCase(name) );
|
||||
parser->Info.Requires.insert(cmSystemTools::LowerCase(name) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -587,7 +798,7 @@ void cmDependsFortranParser_RuleInclude(cmDependsFortranParser* parser,
|
|||
if(parser->Self->FindIncludeFile(dir.c_str(), name, fullName))
|
||||
{
|
||||
// Found the included file. Save it in the set of included files.
|
||||
parser->Includes.insert(fullName);
|
||||
parser->Info.Includes.insert(fullName);
|
||||
|
||||
// Parse it immediately to translate the source inline.
|
||||
cmDependsFortranParser_FilePush(parser, fullName.c_str());
|
||||
|
@ -600,7 +811,7 @@ void cmDependsFortranParser_RuleModule(cmDependsFortranParser* parser,
|
|||
{
|
||||
if(!parser->InInterface )
|
||||
{
|
||||
parser->Provides.insert(cmSystemTools::LowerCase(name));
|
||||
parser->Info.Provides.insert(cmSystemTools::LowerCase(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
#include "cmDepends.h"
|
||||
|
||||
class cmDependsFortranInternals;
|
||||
class cmDependsFortranSourceInfo;
|
||||
|
||||
/** \class cmDependsFortran
|
||||
* \brief Dependency scanner for Fortran object files.
|
||||
*/
|
||||
|
@ -50,17 +53,37 @@ public:
|
|||
std::string& fileName);
|
||||
|
||||
protected:
|
||||
// Finalize the dependency information for the target.
|
||||
virtual bool Finalize(std::ostream& makeDepends,
|
||||
std::ostream& internalDepends);
|
||||
|
||||
// Find all the modules required by the target.
|
||||
void LocateModules();
|
||||
void MatchLocalModules();
|
||||
void MatchRemoteModules(std::istream& fin, const char* moduleDir);
|
||||
void ConsiderModule(const char* name, const char* moduleDir);
|
||||
bool FindModule(std::string const& name, std::string& module);
|
||||
|
||||
// Implement writing/checking methods required by superclass.
|
||||
virtual bool WriteDependencies(
|
||||
const char *src, const char *file,
|
||||
std::ostream& makeDepends, std::ostream& internalDepends);
|
||||
|
||||
// Actually write the depenencies to the streams.
|
||||
bool WriteDependenciesReal(const char *obj,
|
||||
cmDependsFortranSourceInfo const& info,
|
||||
std::ostream& makeDepends,
|
||||
std::ostream& internalDepends);
|
||||
|
||||
// The source file from which to start scanning.
|
||||
std::string SourceFile;
|
||||
|
||||
// The include file search path.
|
||||
std::vector<std::string> const* IncludePath;
|
||||
|
||||
// Internal implementation details.
|
||||
cmDependsFortranInternals* Internal;
|
||||
|
||||
private:
|
||||
cmDependsFortran(cmDependsFortran const&); // Purposely not implemented.
|
||||
void operator=(cmDependsFortran const&); // Purposely not implemented.
|
||||
|
|
Loading…
Reference in New Issue