summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/Platform/Linux-GNU-Fortran.cmake1
-rw-r--r--Modules/Platform/Linux-SunPro-Fortran.cmake2
-rw-r--r--Modules/Platform/Linux-ifort.cmake1
-rw-r--r--Source/cmDependsFortran.cxx74
-rw-r--r--Source/cmDependsFortran.h5
-rw-r--r--Source/cmDocumentVariables.cxx9
-rw-r--r--Source/cmMakefileTargetGenerator.cxx95
-rw-r--r--Source/cmMakefileTargetGenerator.h8
-rw-r--r--Source/cmTarget.cxx10
-rw-r--r--Tests/Fortran/CMakeLists.txt11
-rw-r--r--Tests/Fortran/Executable/CMakeLists.txt2
-rw-r--r--Tests/Fortran/Library/CMakeLists.txt8
12 files changed, 200 insertions, 26 deletions
diff --git a/Modules/Platform/Linux-GNU-Fortran.cmake b/Modules/Platform/Linux-GNU-Fortran.cmake
new file mode 100644
index 0000000..ba13a43
--- /dev/null
+++ b/Modules/Platform/Linux-GNU-Fortran.cmake
@@ -0,0 +1 @@
+SET(CMAKE_Fortran_MODDIR_FLAG -J)
diff --git a/Modules/Platform/Linux-SunPro-Fortran.cmake b/Modules/Platform/Linux-SunPro-Fortran.cmake
index 16ac62c..6994839 100644
--- a/Modules/Platform/Linux-SunPro-Fortran.cmake
+++ b/Modules/Platform/Linux-SunPro-Fortran.cmake
@@ -12,3 +12,5 @@ SET(CMAKE_Fortran_FLAGS_DEBUG_INIT "-g")
SET(CMAKE_Fortran_FLAGS_MINSIZEREL_INIT "-xO2 -xspace -DNDEBUG")
SET(CMAKE_Fortran_FLAGS_RELEASE_INIT "-xO3 -DNDEBUG")
SET(CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT "-g -xO2")
+SET(CMAKE_Fortran_MODDIR_FLAG "-moddir=")
+SET(CMAKE_Fortran_MODPATH_FLAG "-M")
diff --git a/Modules/Platform/Linux-ifort.cmake b/Modules/Platform/Linux-ifort.cmake
index 04dcd62..dc46dd5 100644
--- a/Modules/Platform/Linux-ifort.cmake
+++ b/Modules/Platform/Linux-ifort.cmake
@@ -5,3 +5,4 @@ SET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "-i_dynamic")
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG "-Wl,-rpath,")
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG_SEP ":")
SET(CMAKE_SHARED_LIBRARY_SONAME_Fortran_FLAG "-Wl,-soname,")
+SET(CMAKE_Fortran_MODDIR_FLAG "-module ")
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 30b2d0c..aeb37e7 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -194,6 +194,23 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
// Prepare the module search process.
this->LocateModules();
+ // Get the directory in which stamp files will be stored.
+ const char* stamp_dir =
+ this->LocalGenerator->GetMakefile()->GetCurrentOutputDirectory();
+
+ // Get the directory in which module files will be created.
+ const char* mod_dir;
+ cmMakefile* mf = this->LocalGenerator->GetMakefile();
+ if(const char* target_mod_dir =
+ mf->GetDefinition("CMAKE_Fortran_TARGET_MODULE_DIR"))
+ {
+ mod_dir = target_mod_dir;
+ }
+ else
+ {
+ mod_dir = stamp_dir;
+ }
+
// Actually write dependencies to the streams.
typedef cmDependsFortranInternals::ObjectInfoMap ObjectInfoMap;
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
@@ -201,6 +218,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
i != objInfo.end(); ++i)
{
if(!this->WriteDependenciesReal(i->first.c_str(), i->second,
+ mod_dir, stamp_dir,
makeDepends, internalDepends))
{
return false;
@@ -227,16 +245,35 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
fcName += "/cmake_clean_Fortran.cmake";
cmGeneratedFileStream fcStream(fcName.c_str());
fcStream << "# Remove fortran modules provided by this target.\n";
- fcStream << "FILE(REMOVE\n";
+ fcStream << "FILE(REMOVE";
for(std::set<cmStdString>::const_iterator i = provides.begin();
i != provides.end(); ++i)
{
- std::string mod_upper = cmSystemTools::UpperCase(*i);
- std::string mod_lower = *i;
- fcStream << " \"" << mod_lower << ".mod\""
- << " \"" << mod_lower << ".mod.stamp\""
- << " \"" << mod_upper << ".mod\""
- << " \"" << mod_upper << ".mod.stamp\"\n";
+ 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";
+ std::string stamp = stamp_dir;
+ stamp += "/";
+ stamp += *i;
+ stamp += ".mod.stamp";
+ fcStream << "\n";
+ fcStream << " \"" <<
+ this->LocalGenerator->Convert(mod_lower.c_str(),
+ cmLocalGenerator::START_OUTPUT)
+ << "\"\n";
+ fcStream << " \"" <<
+ this->LocalGenerator->Convert(mod_upper.c_str(),
+ cmLocalGenerator::START_OUTPUT)
+ << "\"\n";
+ fcStream << " \"" <<
+ this->LocalGenerator->Convert(stamp.c_str(),
+ cmLocalGenerator::START_OUTPUT)
+ << "\"\n";
}
fcStream << " )\n";
}
@@ -304,19 +341,19 @@ void cmDependsFortran::LocateModules()
//----------------------------------------------------------------------------
void cmDependsFortran::MatchLocalModules()
{
- const char* moduleDir =
+ const char* stampDir =
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);
+ this->ConsiderModule(i->c_str(), stampDir);
}
}
//----------------------------------------------------------------------------
void cmDependsFortran::MatchRemoteModules(std::istream& fin,
- const char* moduleDir)
+ const char* stampDir)
{
std::string line;
bool doing_provides = false;
@@ -332,7 +369,7 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin,
{
if(doing_provides)
{
- this->ConsiderModule(line.c_str()+1, moduleDir);
+ this->ConsiderModule(line.c_str()+1, stampDir);
}
}
else if(line == "provides")
@@ -348,7 +385,7 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin,
//----------------------------------------------------------------------------
void cmDependsFortran::ConsiderModule(const char* name,
- const char* moduleDir)
+ const char* stampDir)
{
// Locate each required module.
typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap;
@@ -358,7 +395,7 @@ void cmDependsFortran::ConsiderModule(const char* name,
required->second.empty())
{
// The module is provided by a CMake target. It will have a stamp file.
- std::string stampFile = moduleDir;
+ std::string stampFile = stampDir;
stampFile += "/";
stampFile += name;
stampFile += ".mod.stamp";
@@ -371,6 +408,7 @@ bool
cmDependsFortran
::WriteDependenciesReal(const char *obj,
cmDependsFortranSourceInfo const& info,
+ const char* mod_dir, const char* stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends)
{
@@ -379,10 +417,6 @@ cmDependsFortran
// 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;
@@ -414,7 +448,7 @@ cmDependsFortran
// 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;
+ std::string proxy = stamp_dir;
proxy += "/";
proxy += *i;
proxy += ".mod.proxy";
@@ -460,7 +494,7 @@ cmDependsFortran
for(std::set<cmStdString>::const_iterator i = info.Provides.begin();
i != info.Provides.end(); ++i)
{
- std::string proxy = mod_dir;
+ std::string proxy = stamp_dir;
proxy += "/";
proxy += *i;
proxy += ".mod.proxy";
@@ -493,7 +527,7 @@ cmDependsFortran
this->LocalGenerator->Convert(modFile.c_str(),
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::SHELL);
- std::string stampFile = mod_dir;
+ std::string stampFile = stamp_dir;
stampFile += "/";
stampFile += m;
stampFile += ".mod.stamp";
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index c98bad3..e8c4a78 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -60,8 +60,8 @@ protected:
// 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);
+ void MatchRemoteModules(std::istream& fin, const char* stampDir);
+ void ConsiderModule(const char* name, const char* stampDir);
bool FindModule(std::string const& name, std::string& module);
// Implement writing/checking methods required by superclass.
@@ -72,6 +72,7 @@ protected:
// Actually write the depenencies to the streams.
bool WriteDependenciesReal(const char *obj,
cmDependsFortranSourceInfo const& info,
+ const char* mod_dir, const char* stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends);
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index b19bf1c..99628f7 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -680,6 +680,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Variables that Control the Build");
cm->DefineProperty
+ ("CMAKE_Fortran_MODULE_DIRECTORY", cmProperty::VARIABLE,
+ "Fortran module output directory.",
+ "This variable is used to initialize the "
+ "Fortran_MODULE_DIRECTORY property on all the targets. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
("CMAKE_LIBRARY_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
"Where to put all the LIBRARY targets when built.",
"This variable is used to initialize the "
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 13c1b64..0e9ccc5 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -36,6 +36,7 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator()
this->InfoFileStream = 0;
this->FlagFileStream = 0;
this->CustomCommandDriver = OnBuild;
+ this->FortranModuleDirectoryComputed = false;
}
cmMakefileTargetGenerator *
@@ -268,6 +269,12 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
->AddLanguageFlags(flags, lang,
this->LocalGenerator->ConfigurationName.c_str());
+ // Fortran-specific flags computed for this target.
+ if(*l == "Fortran")
+ {
+ this->AddFortranFlags(flags);
+ }
+
// Add shared-library flags if needed.
this->LocalGenerator->AddSharedFlags(flags, lang, shared);
@@ -823,6 +830,15 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< " )\n";
}
+ // Check for a target-specific module output directory.
+ if(const char* mdir = this->GetFortranModuleDirectory())
+ {
+ *this->InfoFileStream
+ << "\n"
+ << "# Fortran module output directory.\n"
+ << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
+ }
+
// and now write the rule to use it
std::vector<std::string> depends;
std::vector<std::string> commands;
@@ -1423,3 +1439,82 @@ cmMakefileTargetGenerator
link_command += " --verbose=$(VERBOSE)";
makefile_commands.push_back(link_command);
}
+
+//----------------------------------------------------------------------------
+const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
+{
+ // Compute the module directory.
+ if(!this->FortranModuleDirectoryComputed)
+ {
+ const char* target_mod_dir =
+ this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
+ const char* moddir_flag =
+ this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
+ if(target_mod_dir && moddir_flag)
+ {
+ // Compute the full path to the module directory.
+ if(cmSystemTools::FileIsFullPath(target_mod_dir))
+ {
+ // Already a full path.
+ this->FortranModuleDirectory = target_mod_dir;
+ }
+ else
+ {
+ // Interpret relative to the current output directory.
+ this->FortranModuleDirectory =
+ this->Makefile->GetCurrentOutputDirectory();
+ this->FortranModuleDirectory += "/";
+ this->FortranModuleDirectory += target_mod_dir;
+ }
+
+ // Make sure the module output directory exists.
+ cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
+ }
+ this->FortranModuleDirectoryComputed = true;
+ }
+
+ // Return the computed directory.
+ if(this->FortranModuleDirectory.empty())
+ {
+ return 0;
+ }
+ else
+ {
+ return this->FortranModuleDirectory.c_str();
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
+{
+ // Add a module output directory flag if necessary.
+ if(const char* mod_dir = this->GetFortranModuleDirectory())
+ {
+ const char* moddir_flag =
+ this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
+ std::string modflag = moddir_flag;
+ modflag += this->Convert(mod_dir,
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL);
+ this->LocalGenerator->AppendFlags(flags, modflag.c_str());
+ }
+
+ // If there is a separate module path flag then duplicate the
+ // include path with it. This compiler does not search the include
+ // path for modules.
+ if(const char* modpath_flag =
+ this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
+ {
+ std::vector<std::string> includes;
+ this->LocalGenerator->GetIncludeDirectories(includes);
+ for(std::vector<std::string>::const_iterator idi = includes.begin();
+ idi != includes.end(); ++idi)
+ {
+ std::string flg = modpath_flag;
+ flg += this->Convert(idi->c_str(),
+ cmLocalGenerator::NONE,
+ cmLocalGenerator::SHELL);
+ this->LocalGenerator->AppendFlags(flags, flg.c_str());
+ }
+ }
+}
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index aa452c9..e997a0a 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -184,6 +184,14 @@ protected:
typedef std::map<cmStdString, cmStdString> MultipleOutputPairsType;
MultipleOutputPairsType MultipleOutputPairs;
+ // Target-wide Fortran module output directory.
+ bool FortranModuleDirectoryComputed;
+ std::string FortranModuleDirectory;
+ const char* GetFortranModuleDirectory();
+
+ // Compute target-specific Fortran language flags.
+ void AddFortranFlags(std::string& flags);
+
//==================================================================
// Convenience routines that do nothing more than forward to
// implementaitons
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index daca41f..747f169 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -285,6 +285,15 @@ void cmTarget::DefineProperties(cmake *cm)
"All Windows-based systems including Cygwin are DLL platforms.");
cm->DefineProperty
+ ("Fortran_MODULE_DIRECTORY", cmProperty::TARGET,
+ "Specify output directory for Fortran modules provided by the target.",
+ "If the target contains Fortran source files that provide modules "
+ "and the compiler supports a module output directory this specifies "
+ "the directory in which the modules will be placed. "
+ "When this property is not set the modules will be placed in the "
+ "build directory corresponding to the target's source directory.");
+
+ cm->DefineProperty
("XCODE_ATTRIBUTE_<an-attribute>", cmProperty::TARGET,
"Set Xcode target attributes directly.",
"Tell the Xcode generator to set '<an-attribute>' to a given value "
@@ -403,6 +412,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
+ this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
// Collect the set of configuration types.
std::vector<std::string> configNames;
diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt
index de1c824..3a299b2 100644
--- a/Tests/Fortran/CMakeLists.txt
+++ b/Tests/Fortran/CMakeLists.txt
@@ -23,9 +23,7 @@ IF(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
in_interface/main.f90
in_interface/module.f90)
- IF(CMAKE_Fortran_COMPILER_ID MATCHES GNU)
- SET(TEST_MODULE_DEPENDS 1)
- ENDIF(CMAKE_Fortran_COMPILER_ID MATCHES GNU)
+ SET(TEST_MODULE_DEPENDS 1)
ENDIF(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
IF(TEST_MODULE_DEPENDS)
@@ -57,6 +55,13 @@ IF(TEST_MODULE_DEPENDS)
)
ADD_CUSTOM_TARGET(ExternalTarget ALL DEPENDS ${testf_BINARY_DIR}/ExternalProject)
+ # Test module output directory if available.
+ IF(CMAKE_Fortran_MODDIR_FLAG)
+ SET(Library_MODDIR "${testf_BINARY_DIR}/Library/modules")
+ ELSE(CMAKE_Fortran_MODDIR_FLAG)
+ SET(Library_MODDIR "${testf_BINARY_DIR}/Library")
+ ENDIF(CMAKE_Fortran_MODDIR_FLAG)
+
ADD_SUBDIRECTORY(Library)
ADD_SUBDIRECTORY(Executable)
ENDIF(TEST_MODULE_DEPENDS)
diff --git a/Tests/Fortran/Executable/CMakeLists.txt b/Tests/Fortran/Executable/CMakeLists.txt
index 7596ff1..40114e4 100644
--- a/Tests/Fortran/Executable/CMakeLists.txt
+++ b/Tests/Fortran/Executable/CMakeLists.txt
@@ -1,4 +1,4 @@
-include_directories(${testf_BINARY_DIR}/Library)
+include_directories(${Library_MODDIR})
include_directories(${testf_BINARY_DIR}/External)
link_directories(${testf_BINARY_DIR}/External)
diff --git a/Tests/Fortran/Library/CMakeLists.txt b/Tests/Fortran/Library/CMakeLists.txt
index 8d62900..fe1368a 100644
--- a/Tests/Fortran/Library/CMakeLists.txt
+++ b/Tests/Fortran/Library/CMakeLists.txt
@@ -1,3 +1,11 @@
+INCLUDE_DIRECTORIES(${Library_MODDIR})
ADD_LIBRARY(subdir_mods a.f90 b.f90)
ADD_EXECUTABLE(subdir_exe main.f90)
TARGET_LINK_LIBRARIES(subdir_exe subdir_mods)
+
+# Test module output directory if available.
+IF(CMAKE_Fortran_MODDIR_FLAG)
+ SET_TARGET_PROPERTIES(subdir_mods PROPERTIES
+ Fortran_MODULE_DIRECTORY modules
+ )
+ENDIF(CMAKE_Fortran_MODDIR_FLAG)