From 9655299f08b5aa04ea63193ebecfa08efae7ca3d Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 6 Aug 2004 14:51:41 -0400 Subject: ENH: initial fortran support --- Modules/CMakeDefaultMakeRuleVariables.cmake | 35 ++++++++ Modules/CMakeDetermineFortranCompiler.cmake | 83 +++++++++++++++++++ Modules/CMakeFortranCompiler.cmake.in | 16 ++++ Modules/CMakeSystemSpecificInformation.cmake | 47 +++++++++++ Modules/CMakeTestFortranCompiler.cmake | 31 ++++++++ Modules/Platform/CYGWIN-g77.cmake | 5 ++ Modules/Platform/g77.cmake | 7 ++ Source/cmGlobalGenerator.cxx | 43 +++++++++- Source/cmLocalUnixMakefileGenerator.cxx | 114 +++++++++++++++++++-------- Source/cmMakefile.cxx | 13 +++ Source/cmMakefile.h | 2 +- Source/cmSystemTools.cxx | 5 ++ Source/cmSystemTools.h | 1 + Source/cmTarget.cxx | 18 +++++ Source/cmTarget.h | 3 + Source/cmTryCompileCommand.cxx | 16 +++- 16 files changed, 403 insertions(+), 36 deletions(-) create mode 100644 Modules/CMakeDetermineFortranCompiler.cmake create mode 100644 Modules/CMakeFortranCompiler.cmake.in create mode 100644 Modules/CMakeTestFortranCompiler.cmake create mode 100644 Modules/Platform/CYGWIN-g77.cmake create mode 100644 Modules/Platform/g77.cmake diff --git a/Modules/CMakeDefaultMakeRuleVariables.cmake b/Modules/CMakeDefaultMakeRuleVariables.cmake index a1a0aad..73d8ab8 100644 --- a/Modules/CMakeDefaultMakeRuleVariables.cmake +++ b/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 + " -o ") +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) " ") 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 + " cr " + " ") +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) " -o -c ") 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 + " -o -c ") +ENDIF(NOT CMAKE_FORTRAN_COMPILE_OBJECT) + IF(NOT CMAKE_C_LINK_EXECUTABLE) SET(CMAKE_C_LINK_EXECUTABLE " -o ") ENDIF(NOT CMAKE_C_LINK_EXECUTABLE) +IF(NOT CMAKE_FORTRAN_LINK_EXECUTABLE) + SET(CMAKE_FORTRAN_LINK_EXECUTABLE + " -o ") +ENDIF(NOT CMAKE_FORTRAN_LINK_EXECUTABLE) + IF(NOT CMAKE_CXX_LINK_EXECUTABLE) SET(CMAKE_CXX_LINK_EXECUTABLE diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake new file mode 100644 index 0000000..52004ee --- /dev/null +++ b/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) diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in new file mode 100644 index 0000000..1bf30a1 --- /dev/null +++ b/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) diff --git a/Modules/CMakeSystemSpecificInformation.cmake b/Modules/CMakeSystemSpecificInformation.cmake index c9f5c29..0abf65d 100644 --- a/Modules/CMakeSystemSpecificInformation.cmake +++ b/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.") diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake new file mode 100644 index 0000000..4937d20 --- /dev/null +++ b/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) diff --git a/Modules/Platform/CYGWIN-g77.cmake b/Modules/Platform/CYGWIN-g77.cmake new file mode 100644 index 0000000..fd5329e --- /dev/null +++ b/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) diff --git a/Modules/Platform/g77.cmake b/Modules/Platform/g77.cmake new file mode 100644 index 0000000..a720f4f --- /dev/null +++ b/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) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index e739ee9..a4c1e25 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/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 { diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx index 16724f5..d866151 100644 --- a/Source/cmLocalUnixMakefileGenerator.cxx +++ b/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_MODULE_CREATE_CXX_FLAGS"}, + {"", "CMAKE_SHARED_MODULE_CREATE_FORTAN_FLAGS"}, {"", "CMAKE_SHARED_MODULE_C_FLAGS"}, + {"", "CMAKE_SHARED_MODULE_FORTRAN_FLAGS"}, {"", "CMAKE_SHARED_MODULE_CXX_FLAGS"}, {"", "CMAKE_SHARED_LIBRARY_C_FLAGS"}, + {"", "CMAKE_SHARED_LIBRARY_FORTRAN_FLAGS"}, {"", "CMAKE_SHARED_LIBRARY_CXX_FLAGS"}, {"", "CMAKE_CXX_LINK_FLAGS"}, {"", "CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS"}, + {"", "CMAKE_SHARED_LIBRARY_CREATE_FORTRAN_FLAGS"}, {"", "CMAKE_SHARED_MODULE_CREATE_C_FLAGS"}, {"", "CMAKE_SHARED_LIBRARY_SONAME_C_FLAG"}, + {"", "CMAKE_SHARED_LIBRARY_SONAME_FORTRAN_FLAG"}, {"", "CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG"}, {"", "CMAKE_C_LINK_FLAGS"}, + {"", "CMAKE_FORTRAN_LINK_FLAGS"}, {"", "CMAKE_AR"}, {"", "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, "", fcompiler.c_str()); cmSystemTools::ReplaceString(s, "", cxxcompiler.c_str()); cmSystemTools::ReplaceString(s, "", ccompiler.c_str()); if(linkFlags) @@ -1165,7 +1174,7 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout, std::vector 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 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: diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 3e3c87b..77bf08d 100644 --- a/Source/cmMakefile.cxx +++ b/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; diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index efca41e..4452622 100644 --- a/Source/cmMakefile.h +++ b/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 diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 4927da8..7dfcdde 100644 --- a/Source/cmSystemTools.cxx +++ b/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" || diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 061b9cc..e0fbffc 100644 --- a/Source/cmSystemTools.h +++ b/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, diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index f914094..7c3fb7a 100644 --- a/Source/cmTarget.cxx +++ b/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::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; +} + diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 804e126..3ba8690 100644 --- a/Source/cmTarget.h +++ b/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 */ diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx index 422b02b..b72f14d 100644 --- a/Source/cmTryCompileCommand.cxx +++ b/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 -- cgit v0.12