Преглед изворни кода

ENH: initial fortran support

Bill Hoffman пре 21 година
родитељ
комит
9655299f08

+ 35 - 0
Modules/CMakeDefaultMakeRuleVariables.cmake

@@ -7,11 +7,16 @@
 # CMAKE_CXX_CREATE_SHARED_MODULE
 # CMAKE_C_CREATE_SHARED_LIBRARY
 # CMAKE_C_CREATE_SHARED_MODULE
+# CMAKE_FORTRAN_CREATE_SHARED_LIBRARY
+# CMAKE_FORTRAN_CREATE_SHARED_MODULE
 # CMAKE_CXX_CREATE_STATIC_LIBRARY
 # CMAKE_C_CREATE_STATIC_LIBRARY
+# CMAKE_FORTRAN_CREATE_STATIC_LIBRARY
 # CMAKE_CXX_COMPILE_OBJECT
 # CMAKE_C_COMPILE_OBJECT
+# CMAKE_FORTRAN_COMPILE_OBJECT
 # CMAKE_C_LINK_EXECUTABLE
+# CMAKE_FORTRAN_LINK_EXECUTABLE
 # CMAKE_CXX_LINK_EXECUTABLE
 
 # variables supplied by the generator at use time
@@ -55,6 +60,7 @@ IF(NOT CMAKE_CXX_CREATE_SHARED_MODULE)
   SET(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
 ENDIF(NOT CMAKE_CXX_CREATE_SHARED_MODULE)
 
+
 # create a C shared library
 IF(NOT CMAKE_C_CREATE_SHARED_LIBRARY)
   SET(CMAKE_C_CREATE_SHARED_LIBRARY
@@ -66,6 +72,17 @@ IF(NOT CMAKE_C_CREATE_SHARED_MODULE)
   SET(CMAKE_C_CREATE_SHARED_MODULE ${CMAKE_C_CREATE_SHARED_LIBRARY})
 ENDIF(NOT CMAKE_C_CREATE_SHARED_MODULE)
 
+# create a FORTRAN shared library
+IF(NOT CMAKE_FORTRAN_CREATE_SHARED_LIBRARY)
+  SET(CMAKE_FORTRAN_CREATE_SHARED_LIBRARY
+      "<CMAKE_FORTRAN_COMPILER> <CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_FORTRAN_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_FORTRAN_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+ENDIF(NOT CMAKE_FORTRAN_CREATE_SHARED_LIBRARY)
+
+# create a FORTRAN shared module just copy the shared library rule
+IF(NOT CMAKE_FORTRAN_CREATE_SHARED_MODULE)
+  SET(CMAKE_FORTRAN_CREATE_SHARED_MODULE ${CMAKE_FORTRAN_CREATE_SHARED_LIBRARY})
+ENDIF(NOT CMAKE_FORTRAN_CREATE_SHARED_MODULE)
+
 # create a C++ static library
 IF(NOT CMAKE_CXX_CREATE_STATIC_LIBRARY)
   SET(CMAKE_CXX_CREATE_STATIC_LIBRARY
@@ -80,6 +97,13 @@ IF(NOT CMAKE_C_CREATE_STATIC_LIBRARY)
       "<CMAKE_RANLIB> <TARGET> ")
 ENDIF(NOT CMAKE_C_CREATE_STATIC_LIBRARY)
 
+# create a Fortran static library
+IF(NOT CMAKE_FORTRAN_CREATE_STATIC_LIBRARY)
+  SET(CMAKE_FORTRAN_CREATE_STATIC_LIBRARY
+      "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS> "
+      "<CMAKE_RANLIB> <TARGET> ")
+ENDIF(NOT CMAKE_FORTRAN_CREATE_STATIC_LIBRARY)
+
 # compile a C++ file into an object file
 IF(NOT CMAKE_CXX_COMPILE_OBJECT)
   SET(CMAKE_CXX_COMPILE_OBJECT
@@ -92,12 +116,23 @@ IF(NOT CMAKE_C_COMPILE_OBJECT)
     "<CMAKE_C_COMPILER> -o <OBJECT>  <FLAGS> -c <SOURCE>")
 ENDIF(NOT CMAKE_C_COMPILE_OBJECT)
 
+# compile a Fortran file into an object file
+IF(NOT CMAKE_FORTRAN_COMPILE_OBJECT)
+  SET(CMAKE_FORTRAN_COMPILE_OBJECT
+    "<CMAKE_FORTRAN_COMPILER> -o <OBJECT>  <FLAGS> -c <SOURCE>")
+ENDIF(NOT CMAKE_FORTRAN_COMPILE_OBJECT)
+
 
 IF(NOT CMAKE_C_LINK_EXECUTABLE)
   SET(CMAKE_C_LINK_EXECUTABLE
     "<CMAKE_C_COMPILER> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>")
 ENDIF(NOT CMAKE_C_LINK_EXECUTABLE)
 
+IF(NOT CMAKE_FORTRAN_LINK_EXECUTABLE)
+  SET(CMAKE_FORTRAN_LINK_EXECUTABLE
+    "<CMAKE_FORTRAN_COMPILER> <CMAKE_FORTRAN_LINK_FLAGS> <LINK_FLAGS> <FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>")
+ENDIF(NOT CMAKE_FORTRAN_LINK_EXECUTABLE)
+
 
 IF(NOT CMAKE_CXX_LINK_EXECUTABLE)
   SET(CMAKE_CXX_LINK_EXECUTABLE

+ 83 - 0
Modules/CMakeDetermineFortranCompiler.cmake

@@ -0,0 +1,83 @@
+# determine the compiler to use for C programs
+# NOTE, a generator may set CMAKE_C_COMPILER before
+# loading this file to force a compiler.
+# use environment variable CCC first if defined by user, next use 
+# the cmake variable CMAKE_GENERATOR_CC which can be defined by a generator
+# as a default compiler
+
+IF(NOT CMAKE_FORTRAN_COMPILER)
+  # prefer the environment variable CC
+  IF($ENV{FC} MATCHES ".+")
+    GET_FILENAME_COMPONENT(CMAKE_FORTRAN_COMPILER_INIT $ENV{FC} PROGRAM PROGRAM_ARGS CMAKE_FORTRAN_FLAGS_ENV_INIT)
+    IF(EXISTS ${CMAKE_FORTRAN_COMPILER_INIT})
+    ELSE(EXISTS ${CMAKE_FORTRAN_COMPILER_INIT})
+      MESSAGE(FATAL_ERROR "Could not find compiler set in environment variable FC:\n$ENV{FC}.") 
+    ENDIF(EXISTS ${CMAKE_FORTRAN_COMPILER_INIT})
+  ENDIF($ENV{FC} MATCHES ".+")
+
+  # next try prefer the compiler specified by the generator
+  IF(CMAKE_GENERATOR_FC) 
+    IF(NOT CMAKE_FORTRAN_COMPILER_INIT)
+      SET(CMAKE_FORTRAN_COMPILER_INIT ${CMAKE_GENERATOR_FC})
+    ENDIF(NOT CMAKE_FORTRAN_COMPILER_INIT)
+  ENDIF(CMAKE_GENERATOR_FC)
+
+
+  # if no compiler has been specified yet, then look for one
+  IF(NOT CMAKE_FORTRAN_COMPILER_INIT)
+  # if not in the envionment then search for the compiler in the path
+    SET(CMAKE_FORTRAN_COMPILER_LIST g77 ifort f77 f90 epcf90 efc ecc)  
+    FIND_PROGRAM(CMAKE_FORTRAN_COMPILER_FULLPATH NAMES ${CMAKE_FORTRAN_COMPILER_LIST} )
+    GET_FILENAME_COMPONENT(CMAKE_FORTRAN_COMPILER_INIT
+                           ${CMAKE_FORTRAN_COMPILER_FULLPATH} NAME)
+    SET(CMAKE_FORTRAN_COMPILER_FULLPATH "${CMAKE_FORTRAN_COMPILER_FULLPATH}" CACHE INTERNAL "full path to the compiler cmake found")
+  ENDIF(NOT CMAKE_FORTRAN_COMPILER_INIT)
+
+  SET(CMAKE_FORTRAN_COMPILER ${CMAKE_FORTRAN_COMPILER_INIT} CACHE STRING "Fortran compiler")
+ENDIF(NOT CMAKE_FORTRAN_COMPILER)
+
+MARK_AS_ADVANCED(CMAKE_FORTRAN_COMPILER)  
+
+FIND_PROGRAM(CMAKE_AR NAMES ar )
+
+FIND_PROGRAM(CMAKE_RANLIB NAMES ranlib)
+IF(NOT CMAKE_RANLIB)
+   SET(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib")
+ENDIF(NOT CMAKE_RANLIB)
+MARK_AS_ADVANCED(CMAKE_RANLIB)
+
+IF(NOT CMAKE_COMPILER_IS_GNUG77_RUN)
+  # test to see if the Fortran compiler is gnu
+  
+  IF(CMAKE_FORTRAN_FLAGS)
+    SET(CMAKE_BOOT_FORTRAN_FLAGS ${CMAKE_FORTRAN_FLAGS})
+  ELSE(CMAKE_FORTRAN_FLAGS)
+    SET(CMAKE_BOOT_FORTRAN_FLAGS $ENV{FFLAGS})
+  ENDIF(CMAKE_FORTRAN_FLAGS)
+  EXEC_PROGRAM(${CMAKE_FORTRAN_COMPILER} ARGS ${CMAKE_BOOT_FORTRAN_FLAGS} -E "\"${CMAKE_ROOT}/Modules/CMakeTestGNU.c\"" OUTPUT_VARIABLE CMAKE_COMPILER_OUTPUT RETURN_VALUE CMAKE_COMPILER_RETURN)
+  SET(CMAKE_COMPILER_IS_GNUG77_RUN 1)
+  IF(NOT CMAKE_COMPILER_RETURN)
+    IF("${CMAKE_COMPILER_OUTPUT}" MATCHES ".*THIS_IS_GNU.*" )
+      SET(CMAKE_COMPILER_IS_GNUG77 1)
+      FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log
+        "Determining if the Fortran compiler is GNU succeeded with "
+        "the following output:\n${CMAKE_COMPILER_OUTPUT}\n\n")
+    ELSE("${CMAKE_COMPILER_OUTPUT}" MATCHES ".*THIS_IS_GNU.*" )
+      FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log
+        "Determining if the Fortran compiler is GNU failed with "
+        "the following output:\n${CMAKE_COMPILER_OUTPUT}\n\n")
+    ENDIF("${CMAKE_COMPILER_OUTPUT}" MATCHES ".*THIS_IS_GNU.*" )
+    IF("${CMAKE_COMPILER_OUTPUT}" MATCHES ".*THIS_IS_MINGW.*" )
+      SET(CMAKE_COMPILER_IS_MINGW 1)
+    ENDIF("${CMAKE_COMPILER_OUTPUT}" MATCHES ".*THIS_IS_MINGW.*" )
+    IF("${CMAKE_COMPILER_OUTPUT}" MATCHES ".*THIS_IS_CYGWIN.*" )
+      SET(CMAKE_COMPILER_IS_CYGWIN 1)
+    ENDIF("${CMAKE_COMPILER_OUTPUT}" MATCHES ".*THIS_IS_CYGWIN.*" )
+  ENDIF(NOT CMAKE_COMPILER_RETURN)
+ENDIF(NOT CMAKE_COMPILER_IS_GNUG77_RUN)
+
+
+# configure variables set in this file for fast reload later on
+CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeFortranCompiler.cmake.in 
+               ${CMAKE_BINARY_DIR}/CMakeFortranCompiler.cmake IMMEDIATE)
+MARK_AS_ADVANCED(CMAKE_AR)

+ 16 - 0
Modules/CMakeFortranCompiler.cmake.in

@@ -0,0 +1,16 @@
+SET(CMAKE_FORTRAN_COMPILER "@CMAKE_FORTRAN_COMPILER@")
+SET(CMAKE_AR "@CMAKE_AR@")
+SET(CMAKE_RANLIB "@CMAKE_RANLIB@")
+SET(CMAKE_COMPILER_IS_GNUCC @CMAKE_COMPILER_IS_GNUCC@)
+SET(CMAKE_FORTRAN_COMPILER_LOADED 1)
+SET(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@)
+SET(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@)
+IF(CMAKE_COMPILER_IS_CYGWIN)
+  SET(CYGWIN 1)
+  SET(UNIX 1)
+ENDIF(CMAKE_COMPILER_IS_CYGWIN)
+
+IF(CMAKE_COMPILER_IS_MINGW)
+  SET(MINGW 1)
+ENDIF(CMAKE_COMPILER_IS_MINGW)
+SET(CMAKE_COMPILER_IS_GNUG77_RUN 1)

+ 47 - 0
Modules/CMakeSystemSpecificInformation.cmake

@@ -135,6 +135,50 @@ IF(NOT CMAKE_SHARED_MODULE_RUNTIME_CXX_FLAG_SEP)
   SET(CMAKE_SHARED_MODULE_RUNTIME_CXX_FLAG_SEP ${CMAKE_SHARED_MODULE_RUNTIME_FLAG_SEP})
 ENDIF(NOT CMAKE_SHARED_MODULE_RUNTIME_CXX_FLAG_SEP)
 
+# Create a set of shared library variable specific to Fortran
+# For 90% of the systems, these are the same flags as the C versions
+# so if these are not set just copy the flags from the c version
+IF(NOT CMAKE_SHARED_LIBRARY_CREATE_FORTRAN_FLAGS)
+  SET(CMAKE_SHARED_LIBRARY_CREATE_FORTRAN_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS})
+ENDIF(NOT CMAKE_SHARED_LIBRARY_CREATE_FORTRAN_FLAGS)
+
+IF(NOT CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS)
+  SET(CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS ${CMAKE_SHARED_LIBRARY_C_FLAGS})
+ENDIF(NOT CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS)
+
+IF(NOT CMAKE_SHARED_LIBRARY_LINK_FORTRAN_FLAGS)
+  SET(CMAKE_SHARED_LIBRARY_LINK_FORTRAN_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_FLAGS})
+ENDIF(NOT CMAKE_SHARED_LIBRARY_LINK_FORTRAN_FLAGS)
+
+IF(NOT CMAKE_SHARED_LIBRARY_RUNTIME_FORTRAN_FLAG)
+  SET(CMAKE_SHARED_LIBRARY_RUNTIME_FORTRAN_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_FLAG}) 
+ENDIF(NOT CMAKE_SHARED_LIBRARY_RUNTIME_FORTRAN_FLAG)
+
+IF(NOT CMAKE_SHARED_LIBRARY_RUNTIME_FORTRAN_FLAG_SEP)
+  SET(CMAKE_SHARED_LIBRARY_RUNTIME_FORTRAN_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_FLAG_SEP})
+ENDIF(NOT CMAKE_SHARED_LIBRARY_RUNTIME_FORTRAN_FLAG_SEP)
+
+# repeat for modules
+IF(NOT CMAKE_SHARED_MODULE_CREATE_FORTRAN_FLAGS)
+  SET(CMAKE_SHARED_MODULE_CREATE_FORTRAN_FLAGS ${CMAKE_SHARED_MODULE_CREATE_C_FLAGS})
+ENDIF(NOT CMAKE_SHARED_MODULE_CREATE_FORTRAN_FLAGS)
+
+IF(NOT CMAKE_SHARED_MODULE_FORTRAN_FLAGS)
+  SET(CMAKE_SHARED_MODULE_FORTRAN_FLAGS ${CMAKE_SHARED_MODULE_C_FLAGS})
+ENDIF(NOT CMAKE_SHARED_MODULE_FORTRAN_FLAGS)
+
+IF(NOT CMAKE_SHARED_MODULE_LINK_FORTRAN_FLAGS)
+  SET(CMAKE_SHARED_MODULE_LINK_FORTRAN_FLAGS ${CMAKE_SHARED_MODULE_LINK_FLAGS})
+ENDIF(NOT CMAKE_SHARED_MODULE_LINK_FORTRAN_FLAGS)
+
+IF(NOT CMAKE_SHARED_MODULE_RUNTIME_FORTRAN_FLAG)
+  SET(CMAKE_SHARED_MODULE_RUNTIME_FORTRAN_FLAG ${CMAKE_SHARED_MODULE_RUNTIME_FLAG}) 
+ENDIF(NOT CMAKE_SHARED_MODULE_RUNTIME_FORTRAN_FLAG)
+
+IF(NOT CMAKE_SHARED_MODULE_RUNTIME_FORTRAN_FLAG_SEP)
+  SET(CMAKE_SHARED_MODULE_RUNTIME_FORTRAN_FLAG_SEP ${CMAKE_SHARED_MODULE_RUNTIME_FLAG_SEP})
+ENDIF(NOT CMAKE_SHARED_MODULE_RUNTIME_FORTRAN_FLAG_SEP)
+
 # include default rules that work for most unix like systems and compilers
 # this file will not set anything if it is already set
 INCLUDE(${CMAKE_ROOT}/Modules/CMakeDefaultMakeRuleVariables.cmake)
@@ -158,6 +202,9 @@ SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_ENV_INIT} $ENV{CXXFLAGS} ${CMAKE_CXX_FLA
 SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_ENV_INIT} $ENV{CFLAGS} ${CMAKE_C_FLAGS_INIT}" CACHE STRING
      "Flags for C compiler.")
 
+SET (CMAKE_FORTRAN_FLAGS "${CMAKE_FORTRAN_FLAGS_ENV_INIT} $ENV{FFLAGS} ${CMAKE_FORTRAN_FLAGS_INIT}" CACHE STRING
+     "Flags for Fortran compiler.")
+
 SET (CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS_INIT} $ENV{LDFLAGS}
      CACHE STRING "Flags used by the linker.")
 

+ 31 - 0
Modules/CMakeTestFortranCompiler.cmake

@@ -0,0 +1,31 @@
+# This file is used by EnableLanguage in cmGlobalGenerator to
+# determine that that selected C compiler can actually compile
+# and link the most basic of programs.   If not, a fatal error
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+IF(NOT CMAKE_FORTRAN_COMPILER_WORKS)
+  MESSAGE(STATUS "Check for working Fortran compiler: ${CMAKE_FORTRAN_COMPILER}")
+  FILE(WRITE ${CMAKE_BINARY_DIR}/CMakeTmp/testFortranCompiler.f
+    "\tPROGRAM TESTFORTRAN\n"
+    "\tPRINT *, 'Hello'\n"
+    "\tEND\n")
+  TRY_COMPILE(CMAKE_FORTRAN_COMPILER_WORKS ${CMAKE_BINARY_DIR} 
+    ${CMAKE_BINARY_DIR}/CMakeTmp/testFortranCompiler.f
+    OUTPUT_VARIABLE OUTPUT)
+ENDIF(NOT CMAKE_FORTRAN_COMPILER_WORKS)
+
+IF(NOT CMAKE_FORTRAN_COMPILER_WORKS)
+  MESSAGE(STATUS "Check for working Fortran compiler: ${CMAKE_FORTRAN_COMPILER} -- broken")
+  FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeError.log
+    "Determining if the Fortran compiler works failed with "
+    "the following output:\n${OUTPUT}\n\n")
+  MESSAGE(FATAL_ERROR "The Fortran compiler \"${CMAKE_FORTRAN_COMPILER}\" "
+    "is not able to compile a simple test program.\nIt fails "
+    "with the following output:\n ${OUTPUT}\n\n"
+    "CMake will not be able to correctly generate this project.")
+ELSE(NOT CMAKE_FORTRAN_COMPILER_WORKS)
+  MESSAGE(STATUS "Check for working Fortran compiler: ${CMAKE_FORTRAN_COMPILER} -- works")
+  FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log
+    "Determining if the Fortran compiler works passed with "
+    "the following output:\n${OUTPUT}\n\n")
+ENDIF(NOT CMAKE_FORTRAN_COMPILER_WORKS)

+ 5 - 0
Modules/Platform/CYGWIN-g77.cmake

@@ -0,0 +1,5 @@
+SET(CMAKE_SHARED_LIBRARY_PREFIX "lib")
+SET(CMAKE_SHARED_LIBRARY_SUFFIX ".dll")
+SET(CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS "") 
+SET(CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS "")
+INCLUDE(${CMAKE_ROOT}/Modules/Platform/g77.cmake)

+ 7 - 0
Modules/Platform/g77.cmake

@@ -0,0 +1,7 @@
+IF(CMAKE_COMPILER_IS_GNUG77)
+  SET (CMAKE_FORTRAN_FLAGS_INIT "")
+  SET (CMAKE_FORTRAN_FLAGS_DEBUG_INIT "-g")
+  SET (CMAKE_FORTRAN_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG")
+  SET (CMAKE_FORTRAN_FLAGS_RELEASE_INIT "-O3 -DNDEBUG")
+  SET (CMAKE_FORTRAN_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")
+ENDIF(CMAKE_COMPILER_IS_GNUG77)

+ 40 - 3
Source/cmGlobalGenerator.cxx

@@ -108,10 +108,10 @@ void cmGlobalGenerator::EnableLanguage(const char* lang,
     }
   bool needCBackwards = false;
   bool needCXXBackwards = false;
-
+  bool needTestFortran = false;
   if (!isLocal &&
       !this->GetLanguageEnabled("C") && !this->GetLanguageEnabled("CXX") &&
-      !this->GetLanguageEnabled("JAVA"))
+      !this->GetLanguageEnabled("JAVA") && !this->GetLanguageEnabled("FORTRAN"))
     {
 #if defined(_WIN32) && !defined(__CYGWIN__) 
     /* Windows version number data.  */
@@ -186,6 +186,17 @@ void cmGlobalGenerator::EnableLanguage(const char* lang,
     mf->ReadListFile(0,determineCFile.c_str());
     this->SetLanguageEnabled("JAVA");
     }
+  // check for a Fortran compiler and configure it
+  if(!isLocal &&
+     !this->GetLanguageEnabled("FORTRAN") &&
+     strcmp(lang, "FORTRAN") == 0)
+    {
+    needTestFortran = true;
+    std::string determineCFile = root;
+    determineCFile += "/Modules/CMakeDetermineFortranCompiler.cmake";
+    mf->ReadListFile(0,determineCFile.c_str());
+    this->SetLanguageEnabled("FORTRAN");
+    }
    
   std::string fpath = rootBin;
   if(!mf->GetDefinition("CMAKE_SYSTEM_LOADED"))
@@ -216,7 +227,14 @@ void cmGlobalGenerator::EnableLanguage(const char* lang,
     mf->ReadListFile(0,fpath.c_str());
     this->SetLanguageEnabled("JAVA");
     }
-  if ( lang[0] == 'C' && !mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
+  if(strcmp(lang, "FORTRAN") == 0 && !mf->GetDefinition("CMAKE_FORTRAN_COMPILER_LOADED"))
+    {
+    fpath = rootBin; 
+    fpath += "/CMakeFortranCompiler.cmake";
+    mf->ReadListFile(0,fpath.c_str());
+    this->SetLanguageEnabled("FORTRAN");
+    }
+  if ( (lang[0] == 'C' || lang[0] == 'F') && !mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED"))
     {
     fpath = root;
     fpath += "/Modules/CMakeSystemSpecificInformation.cmake";
@@ -259,6 +277,16 @@ void cmGlobalGenerator::EnableLanguage(const char* lang,
           }
         }
       }
+    if(needTestFortran)
+      {
+      if (!m_CMakeInstance->GetIsInTryCompile()) 
+        {
+        std::string ifpath = root + "/Modules/CMakeTestFortranCompiler.cmake";
+        mf->ReadListFile(0,ifpath.c_str());
+        }
+      }
+    
+
     // if we are from the top, always define this
     mf->AddDefinition("RUN_CONFIGURE", true);
     }
@@ -479,6 +507,15 @@ int cmGlobalGenerator::TryCompile(const char *, const char *bindir,
     {
     makeCommand += " ";
     makeCommand += target;
+#if defined(_WIN32) || defined(__CYGWIN__)
+    std::string tmp = target;
+    // if the target does not already end in . something 
+    // then assume .exe
+    if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
+      {
+      makeCommand += ".exe";
+      }
+#endif // WIN32
     }
   else
     {

+ 83 - 31
Source/cmLocalUnixMakefileGenerator.cxx

@@ -717,7 +717,7 @@ void cmLocalUnixMakefileGenerator::OutputLinkLibraries(std::ostream& fout,
   // Some search paths should never be emitted
   emitted.insert("");
   emitted.insert("/usr/lib");
-  std::string libPathFlag = m_Makefile->GetDefinition("CMAKE_LIBRARY_PATH_FLAG");
+  std::string libPathFlag = m_Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
   std::string libLinkFlag = m_Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
   // collect all the flags needed for linking libraries
   std::string linkLibs;
@@ -984,17 +984,23 @@ static RuleVariables ruleReplaceVars[] =
 {
   {"<CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS>", "CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS"},
   {"<CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS>", "CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS"}, 
+  {"<CMAKE_SHARED_MODULE_CREATE_FORTAN_FLAGS>", "CMAKE_SHARED_MODULE_CREATE_FORTAN_FLAGS"}, 
   {"<CMAKE_SHARED_MODULE_C_FLAGS>", "CMAKE_SHARED_MODULE_C_FLAGS"},
+  {"<CMAKE_SHARED_MODULE_FORTRAN_FLAGS>", "CMAKE_SHARED_MODULE_FORTRAN_FLAGS"},
   {"<CMAKE_SHARED_MODULE_CXX_FLAGS>", "CMAKE_SHARED_MODULE_CXX_FLAGS"},
   {"<CMAKE_SHARED_LIBRARY_C_FLAGS>", "CMAKE_SHARED_LIBRARY_C_FLAGS"},
+  {"<CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS>", "CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS"},
   {"<CMAKE_SHARED_LIBRARY_CXX_FLAGS>", "CMAKE_SHARED_LIBRARY_CXX_FLAGS"},
   {"<CMAKE_CXX_LINK_FLAGS>", "CMAKE_CXX_LINK_FLAGS"},
 
   {"<CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS>", "CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS"},
+  {"<CMAKE_SHARED_LIBRARY_CREATE_FORTRAN_FLAGS>", "CMAKE_SHARED_LIBRARY_CREATE_FORTRAN_FLAGS"},
   {"<CMAKE_SHARED_MODULE_CREATE_C_FLAGS>", "CMAKE_SHARED_MODULE_CREATE_C_FLAGS"},
   {"<CMAKE_SHARED_LIBRARY_SONAME_C_FLAG>", "CMAKE_SHARED_LIBRARY_SONAME_C_FLAG"},
+  {"<CMAKE_SHARED_LIBRARY_SONAME_FORTRAN_FLAG>", "CMAKE_SHARED_LIBRARY_SONAME_FORTRAN_FLAG"},
   {"<CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG>", "CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG"},
   {"<CMAKE_C_LINK_FLAGS>", "CMAKE_C_LINK_FLAGS"},
+  {"<CMAKE_FORTRAN_LINK_FLAGS>", "CMAKE_FORTRAN_LINK_FLAGS"},
 
   {"<CMAKE_AR>", "CMAKE_AR"},
   {"<CMAKE_RANLIB>", "CMAKE_RANLIB"},
@@ -1021,6 +1027,9 @@ cmLocalUnixMakefileGenerator::ExpandRuleVariables(std::string& s,
     m_Makefile->GetSafeDefinition("CMAKE_CXX_COMPILER"));
   std::string ccompiler = this->ConvertToOutputForExisting(
     m_Makefile->GetSafeDefinition("CMAKE_C_COMPILER"));
+  std::string fcompiler = this->ConvertToOutputForExisting(
+    m_Makefile->GetSafeDefinition("CMAKE_FORTRAN_COMPILER"));
+  cmSystemTools::ReplaceString(s, "<CMAKE_FORTRAN_COMPILER>", fcompiler.c_str());
   cmSystemTools::ReplaceString(s, "<CMAKE_CXX_COMPILER>", cxxcompiler.c_str());
   cmSystemTools::ReplaceString(s, "<CMAKE_C_COMPILER>", ccompiler.c_str());
   if(linkFlags)
@@ -1165,7 +1174,7 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
 
   std::vector<std::string> commands;
   std::string cmakecommand = this->ConvertToOutputForExisting(
-    m_Makefile->GetDefinition("CMAKE_COMMAND"));
+    m_Makefile->GetRequiredDefinition("CMAKE_COMMAND"));
 
   // Remove any existing files for this library.
   std::string remove = cmakecommand;
@@ -1199,7 +1208,7 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
 
   // collect up the build rules
   std::vector<std::string> rules;
-  rules.push_back(m_Makefile->GetDefinition(createVariable));
+  rules.push_back(m_Makefile->GetRequiredDefinition(createVariable));
   // expand multi-command semi-colon separated lists
   // of commands into separate commands
   cmSystemTools::ExpandList(rules, commands);
@@ -1261,9 +1270,9 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
                          depend.c_str(),
                          commands);
     }
+  // Add a target with the canonical name (no prefix, suffix or path). 
+  this->OutputMakeRule(fout, comment, name, tgt.c_str(), 0); 
 
-  // Add a target with the canonical name (no prefix, suffix or path).
-  this->OutputMakeRule(fout, comment, name, tgt.c_str(), 0);
 }
 
 void cmLocalUnixMakefileGenerator::OutputSharedLibraryRule(std::ostream& fout,  
@@ -1274,11 +1283,19 @@ void cmLocalUnixMakefileGenerator::OutputSharedLibraryRule(std::ostream& fout,
   if(t.HasCxx())
     {
     createRule = "CMAKE_CXX_CREATE_SHARED_LIBRARY";
-    }
+    } 
   else
     {
-    createRule = "CMAKE_C_CREATE_SHARED_LIBRARY";
+    if(t.HasFortran())
+      { 
+      createRule = "CMAKE_FORTRAN_CREATE_SHARED_LIBRARY";
+      }
+    else
+      {
+      createRule = "CMAKE_C_CREATE_SHARED_LIBRARY";
+      }
     }
+  
   std::string buildType =  m_Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
   buildType = cmSystemTools::UpperCase(buildType); 
   std::string linkFlags = m_Makefile->GetSafeDefinition("CMAKE_SHARED_LINKER_FLAGS");
@@ -1427,7 +1444,8 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
     {
     needsLocalTarget = true;
     }
-  std::string objs = "$(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ") $(" + this->CreateMakeVariable(name, "_EXTERNAL_OBJS") + ") ";
+  std::string objs = "$(" + this->CreateMakeVariable(name, "_SRC_OBJS") + 
+    ") $(" + this->CreateMakeVariable(name, "_EXTERNAL_OBJS") + ") ";
   std::string depend = "$(";
   depend += this->CreateMakeVariable(name, "_SRC_OBJS") 
     + ") $(" + this->CreateMakeVariable(name, "_EXTERNAL_OBJS") 
@@ -1445,7 +1463,7 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
 
   if(t.HasCxx())
     {
-    rules.push_back(m_Makefile->GetDefinition("CMAKE_CXX_LINK_EXECUTABLE"));
+    rules.push_back(m_Makefile->GetRequiredDefinition("CMAKE_CXX_LINK_EXECUTABLE"));
     flags += m_Makefile->GetSafeDefinition("CMAKE_CXX_FLAGS");
     flags += " ";
     flags += m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_CXX_FLAGS");
@@ -1453,11 +1471,22 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
     }
   else
     {
-    rules.push_back(m_Makefile->GetDefinition("CMAKE_C_LINK_EXECUTABLE"));
-    flags += m_Makefile->GetSafeDefinition("CMAKE_C_FLAGS");
-    flags += " ";
-    flags += m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_C_FLAGS");
-    flags += " ";
+    if(t.HasFortran())
+      {
+      rules.push_back(m_Makefile->GetRequiredDefinition("CMAKE_FORTRAN_LINK_EXECUTABLE"));
+      flags += m_Makefile->GetSafeDefinition("CMAKE_FORTRAN_FLAGS");
+      flags += " ";
+      flags += m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS");
+      flags += " ";
+      }
+    else
+      {
+      rules.push_back(m_Makefile->GetRequiredDefinition("CMAKE_C_LINK_EXECUTABLE"));
+      flags += m_Makefile->GetSafeDefinition("CMAKE_C_FLAGS");
+      flags += " ";
+      flags += m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_C_FLAGS");
+      flags += " ";
+      }
     }
   cmOStringStream linklibs;
   this->OutputLinkLibraries(linklibs, 0, t);
@@ -1540,15 +1569,14 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
                          depend.c_str(),
                          commands);
     }
-
-  // Add a target with the canonical name (no prefix, suffix or path).
-  // Note that on some platforms the "local target" added above will
-  // actually be the canonical name and will have set "target"
-  // correctly.  Do not duplicate this target.
-  if(target != name)
-    {
-    this->OutputMakeRule(fout, comment.c_str(), name, target.c_str(), 0);
-    }
+  // Add a target with the canonical name (no prefix, suffix or path). 
+  // Note that on some platforms the "local target" added above will 
+  // actually be the canonical name and will have set "target" 
+  // correctly.  Do not duplicate this target. 
+  if(target != name) 
+    { 
+    this->OutputMakeRule(fout, comment.c_str(), name, target.c_str(), 0); 
+    } 
 }
 
 
@@ -2476,7 +2504,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout)
     }
   
   std::string cmakecommand = this->ConvertToOutputForExisting(
-    m_Makefile->GetDefinition("CMAKE_COMMAND"));
+    m_Makefile->GetRequiredDefinition("CMAKE_COMMAND"));
   fout << "CMAKE_COMMAND = "
        << cmakecommand
        << "\n";
@@ -2699,14 +2727,14 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
   
   this->OutputSourceObjectBuildRules(fout);
   // find ctest
-  std::string ctest = m_Makefile->GetDefinition("CMAKE_COMMAND");
+  std::string ctest = m_Makefile->GetRequiredDefinition("CMAKE_COMMAND");
   ctest = cmSystemTools::GetFilenamePath(ctest.c_str());
   ctest += "/";
   ctest += "ctest";
   ctest += cmSystemTools::GetExecutableExtension();
   if(!cmSystemTools::FileExists(ctest.c_str()))
     {
-    ctest = m_Makefile->GetDefinition("CMAKE_COMMAND");
+    ctest = m_Makefile->GetRequiredDefinition("CMAKE_COMMAND");
     ctest = cmSystemTools::GetFilenamePath(ctest.c_str());
     ctest += "/Debug/";
     ctest += "ctest";
@@ -2714,7 +2742,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
     }
   if(!cmSystemTools::FileExists(ctest.c_str()))
     {
-    ctest = m_Makefile->GetDefinition("CMAKE_COMMAND");
+    ctest = m_Makefile->GetRequiredDefinition("CMAKE_COMMAND");
     ctest = cmSystemTools::GetFilenamePath(ctest.c_str());
     ctest += "/Release/";
     ctest += "ctest";
@@ -2727,7 +2755,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
       {
       return;
       }
-    ctest = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
+    ctest = m_Makefile->GetRequiredDefinition("EXECUTABLE_OUTPUT_PATH");
     ctest += "/ctest";
     }
   if (m_Makefile->IsOn("CMAKE_TESTING_ENABLED"))
@@ -2745,7 +2773,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
     {
     // We are building CMake itself.  We cannot use the original
     // executable to install over itself.
-    std::string rule = m_Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
+    std::string rule = m_Makefile->GetRequiredDefinition("EXECUTABLE_OUTPUT_PATH");
     rule += "/cmake";
     rule = cmSystemTools::ConvertToOutputPath(rule.c_str());
     rule += " -P cmake_install.cmake";
@@ -2794,7 +2822,7 @@ OutputBuildObjectFromSource(std::ostream& fout,
     {
     case cmSystemTools::C_FILE_FORMAT:
       {
-      rules.push_back(m_Makefile->GetDefinition("CMAKE_C_COMPILE_OBJECT"));
+      rules.push_back(m_Makefile->GetRequiredDefinition("CMAKE_C_COMPILE_OBJECT"));
       flags += m_Makefile->GetSafeDefinition("CMAKE_C_FLAGS");
       flags += " ";
       if(buildType.size())
@@ -2818,7 +2846,7 @@ OutputBuildObjectFromSource(std::ostream& fout,
       }
     case cmSystemTools::CXX_FILE_FORMAT:
       {
-      rules.push_back(m_Makefile->GetDefinition("CMAKE_CXX_COMPILE_OBJECT"));
+      rules.push_back(m_Makefile->GetRequiredDefinition("CMAKE_CXX_COMPILE_OBJECT"));
       flags += m_Makefile->GetSafeDefinition("CMAKE_CXX_FLAGS");
       flags += " "; 
       if(buildType.size())
@@ -2840,6 +2868,30 @@ OutputBuildObjectFromSource(std::ostream& fout,
         }
       break;
       }
+    case cmSystemTools::FORTRAN_FILE_FORMAT:
+       {
+       rules.push_back(m_Makefile->GetRequiredDefinition("CMAKE_FORTRAN_COMPILE_OBJECT"));
+       flags += m_Makefile->GetSafeDefinition("CMAKE_FORTRAN_FLAGS");
+       flags += " "; 
+       if(buildType.size())
+         {
+         std::string build = "CMAKE_FORTRAN_FLAGS_";
+         build += buildType;
+         flags +=  m_Makefile->GetSafeDefinition(build.c_str());
+         flags += " ";
+         }
+       if(shared)
+         {
+         flags += m_Makefile->GetSafeDefinition("CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS");
+         flags += " ";
+         }
+       if(cmSystemTools::IsOn(m_Makefile->GetDefinition("BUILD_SHARED_LIBS")))
+         {
+         flags += m_Makefile->GetSafeDefinition("CMAKE_SHARED_BUILD_FORTRAN_FLAGS");
+         flags += " ";
+         }
+       break;
+       }
     case cmSystemTools::HEADER_FILE_FORMAT:
       return;
     case cmSystemTools::DEFINITION_FILE_FORMAT:

+ 13 - 0
Source/cmMakefile.cxx

@@ -1346,6 +1346,19 @@ bool cmMakefile::IsOn(const char* name) const
   return cmSystemTools::IsOn(value);
 }
 
+const char* cmMakefile::GetRequiredDefinition(const char* name) const
+{
+  const char* ret = this->GetDefinition(name);
+  if(!ret)
+    {
+    cmSystemTools::Error("Error required internal CMake variable not set, cmake may be not be built correctly.\n",
+                         "Missing variable is:\n",
+                         name);
+    return "";
+    }
+  return ret;
+}
+
 const char* cmMakefile::GetDefinition(const char* name) const
 {
   const char* def = 0;

+ 1 - 1
Source/cmMakefile.h

@@ -503,7 +503,7 @@ public:
    */
   const char* GetDefinition(const char*) const;
   const char* GetSafeDefinition(const char*) const;
-
+  const char* GetRequiredDefinition(const char* name) const;
   /**
    * Get the list of all variables in the current space. If argument
    * cacheonly is specified and is greater than 0, then only cache

+ 5 - 0
Source/cmSystemTools.cxx

@@ -1095,6 +1095,11 @@ cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext)
     ext == "m" || ext == ".m" ||
     ext == "mm" || ext == ".mm"
     ) { return cmSystemTools::CXX_FILE_FORMAT; }
+  if ( 
+    ext == "f" || ext == ".f" ||
+    ext == "F" || ext == ".F" ||
+    ext == "f77" || ext == ".f77" 
+    ) { return cmSystemTools::FORTRAN_FILE_FORMAT; }
   if ( ext == "java" || ext == ".java" ) { return cmSystemTools::JAVA_FILE_FORMAT; }
   if ( 
     ext == "H" || ext == ".H" || 

+ 1 - 0
Source/cmSystemTools.h

@@ -211,6 +211,7 @@ public:
     NO_FILE_FORMAT = 0,
     C_FILE_FORMAT,
     CXX_FILE_FORMAT,
+    FORTRAN_FILE_FORMAT,
     JAVA_FILE_FORMAT,
     HEADER_FILE_FORMAT,
     RESOURCE_FILE_FORMAT,

+ 18 - 0
Source/cmTarget.cxx

@@ -437,6 +437,24 @@ bool cmTarget::HasCxx() const
   return false;
 }
 
+bool cmTarget::HasFortran() const
+{
+  if(this->GetProperty("HAS_FORTRAN"))
+    {
+    return true;
+    }
+  for(std::vector<cmSourceFile*>::const_iterator i =  m_SourceFiles.begin();
+      i != m_SourceFiles.end(); ++i)
+    {
+    if(cmSystemTools::GetFileFormat((*i)->GetSourceExtension().c_str())
+       == cmSystemTools::FORTRAN_FILE_FORMAT)
+      {
+      return true;
+      }
+    }
+  return false;
+}
+
 
 
 

+ 3 - 0
Source/cmTarget.h

@@ -87,6 +87,9 @@ public:
 
   ///! does this target have a cxx file in it
   bool HasCxx() const;
+
+  ///! does this target have a fortran file in it
+  bool HasFortran() const;
   /**
    * Get the list of the source files used by this target
    */

+ 15 - 1
Source/cmTryCompileCommand.cxx

@@ -156,10 +156,14 @@ int cmTryCompileCommand::CoreTryCompileCode(
       {
       fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE CXX)\n");      
       }
+    else if ( format == cmSystemTools::FORTRAN_FILE_FORMAT )
+      {
+      fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE FORTRAN)\n");      
+      }
     else
       {
       cmSystemTools::Error("Unknown file format for file: ", source.c_str(), 
-                           "; TRY_COMPILE only works for C and CXX files");
+                           "; TRY_COMPILE only works for C, CXX, and FORTRAN files");
       return -1;
       }
     const char* cflags = mf->GetDefinition("CMAKE_C_FLAGS"); 
@@ -181,6 +185,16 @@ int cmTryCompileCommand::CoreTryCompileCode(
         }
       fprintf(fout, " ${COMPILE_DEFINITIONS}\")\n");
       }
+    if(format == cmSystemTools::FORTRAN_FILE_FORMAT )
+      {
+      const char* fflags = mf->GetDefinition("CMAKE_FORTRAN_FLAGS");
+      fprintf(fout, "SET(CMAKE_FORTRAN_FLAGS \"${CMAKE_FORTRAN_FLAGS} ");
+      if(fflags)
+        {
+        fprintf(fout, " %s ", fflags);
+        }
+      fprintf(fout, " ${COMPILE_DEFINITIONS}\")\n");
+      }
     fprintf(fout, "INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES})\n");
     fprintf(fout, "LINK_DIRECTORIES(${LINK_DIRECTORIES})\n");
     // handle any compile flags we need to pass on