[CMake] What's the best way to support additional compilers for an "official" CMake language such as Fortran

Alan W. Irwin irwin at beluga.phys.uvic.ca
Tue Jan 19 17:37:46 EST 2010


Hi Brad:

Thanks for your reply which must have crossed with mine asking for a response.

On 2010-01-19 14:06-0500 Brad King wrote:

> On 1/15/2010 5:58 PM, Alan W. Irwin wrote:
>> The PLplot project has been supporting some additional Fortran
>> compilers
>
> What compilers?

These platform files (see attached) have all been developed by Arjen Markus,
one of our windows developers. Thus, I don't know much about them or even
whether they are needed any more.  However, from reading the initial commit
messages for these files they deal with the following compilers/platforms.

* gfortran on Cygwin

* gfortran under MinGW

* Compaq Visual Fortran on Windows

>
> FYI, the Compiler/* and Platform/* modules have been refactored
> a bit in CVS HEAD CMake.  The changes break compiler- and platform-
> specific information down with more granularity, making it easier
> to add new compilers.  We've added support for PathScale and PGI.
>
>> via files in cmake/modules/Platform in our source tree where we use
>> 
>> set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules)
>> 
>> This CMake_MODULE_PATH approach requires that we put a slightly modified
>> version of CMakeFortranInformation.cmake in cmake/modules that searches
>> ${CMAKE_MODULE_PATH}/Platform locations as well as
>> ${CMAKE_ROOT}/Modules/Platform. That's pretty clumsy but this procedure has
>> worked fine for CMake-2.6.x.
>
> What change did you make to CMakeFortranInformation.cmake?  We should
> be able to modify the CMake-provided version to do this.

That would be wonderful.

I have attached a patch relative to the CMake-2.6.0 version of that file.
Basically wherever CMAKE_ROOT is mentioned, you also have to give a
CMake_MODULE_PATH alternative.

>
>> However, I am having trouble with the cmake-2.8.0 case. (I am getting
>> strange errors that use g++ rather than gfortran as the Fortran linker for
>> the static Fortran library case).
>
> Static libraries don't link, they are archives, so I assume you mean
> that linking an executable to a static library is using the C++ linker.
>
> This is a feature of CMake 2.8.  CMake tracks the languages involved
> in each target.  If any C++ is involved, either directly or through
> a linked library, then it uses the C++ linker.  This is necessary to
> initialize the C++ language runtime correctly.  If Fortran is involved
> too then it uses the C++ linker and explicitly passes Fortran language
> libraries.

The linking is more complicated then that.  The test executable is linked to
a static PLplot library which in turn is linked to (a few) shared system
libraries (which I am virtually positive are written in C rather than C++,
but let me get back to you on that.  If I simply put the unmodified version
of the CMake 2.8 version of CMakeFortranInformation.cmake into our
CMAKE_MODULE_PATH location, then the linker is chosen to be g++ which fails.
If I remove CMakeFortranInformation.cmake completely from our
CMAKE_MODULE_PATH location, then the linker is gfortran which succeeds.
Note, I am only summarizing based on my memory of recent tests here so I
will make an additional investigation now based on what you have said and
report back the exact error messages, ldd results for the involved
libraries, etc.

>
>> My guess is I need to add additional
>> Fortran support files in cmake/modules for the CMake-2.8.0 case. But that
>> is clumsier still and requires that we immediately drop CMake-2.6.x
>> support.
>
> Create a language module directory for each version of CMake.
>
>> Thus, I am wondering if there is a better procedure (or whether such a
>> procedure could be implemented within CMake) to allow convenient CMake
>> support for a project like PLplot to support additional Fortran compilers
>> (or any additional compilers for a CMake-supported language like Fortran)
>> without requiring our users patch their installed version of CMake.
>
> The above-mentioned modification to CMakeFortranInformation.cmake should
> handle this.
>
>> Of course, the long-term solution to this problem is to contribute our 
>> files
>> that support additional Fortran compilers to CMake. We would be happy to do
>> that, but that probably involves considerable delay until they are accepted
>> into an official CMake release
>
> If you had started that process back when you wrote them for 2.6
> then perhaps they would have been in 2.8.

The Compaq Visual Fortran one was written in Nov 2006 for cmake 2.4 with an
accompanying wishlist bug report by Arjen asking for that Platform file to
be adopted into CMake.  But IIRC that donation was silently ignored for
whatever reason. Note that bug report may have gotten lost in the conversion
from your old bug system to mantis and in any case we haven't followed up
ourselves on this until now so we are not trying to blame anybody for that
old situation; we just want to find a solution for now.

> Why?  CMake's tests exercise just about everything CMake knows
> about the compilers.  I think direct contribution to CMake should
> be done immediately.

I agree.  Because of the situation explained above, we just got into the
habit of creating those platform files ourselves without bothering to donate
them.  I assume Arjen would still be willing to donate all of the attached
three files to the CMake project (if you find them useful), but I assume he
is lurking on list here and will speak for himself on that issue.

Alan
__________________________
Alan W. Irwin

Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).

Programming affiliations with the FreeEOS equation-of-state implementation
for stellar interiors (freeeos.sf.net); PLplot scientific plotting software
package (plplot.org); the libLASi project (unifont.org/lasi); the Loads of
Linux Links project (loll.sf.net); and the Linux Brochure Project
(lbproject.sf.net).
__________________________

Linux-powered Science
__________________________
-------------- next part --------------
--- /home/software/cmake/install_2.6.0/share/cmake-2.6/Modules/CMakeFortranInformation.cmake	2008-05-05 11:25:53.000000000 -0700
+++ ./CMakeFortranInformation.cmake	2010-01-15 13:28:22.000000000 -0800
@@ -9,12 +9,19 @@
   SET(CMAKE_BASE_NAME g77)
 ENDIF(CMAKE_COMPILER_IS_GNUG77)
 IF(CMAKE_Fortran_COMPILER_ID)
-  IF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Fortran_COMPILER_ID}-Fortran.cmake)
+  IF(EXISTS ${CMAKE_MODULE_PATH}/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Fortran_COMPILER_ID}-Fortran.cmake OR EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Fortran_COMPILER_ID}-Fortran.cmake)
     SET(CMAKE_BASE_NAME ${CMAKE_Fortran_COMPILER_ID}-Fortran)
-  ENDIF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Fortran_COMPILER_ID}-Fortran.cmake)
+  ENDIF(EXISTS ${CMAKE_MODULE_PATH}/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Fortran_COMPILER_ID}-Fortran.cmake OR EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_Fortran_COMPILER_ID}-Fortran.cmake)
 ENDIF(CMAKE_Fortran_COMPILER_ID)
-SET(CMAKE_SYSTEM_AND_Fortran_COMPILER_INFO_FILE
+IF(EXISTS ${CMAKE_MODULE_PATH}/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake)
+  # Use this file if it exists.
+  SET(CMAKE_SYSTEM_AND_Fortran_COMPILER_INFO_FILE
+  ${CMAKE_MODULE_PATH}/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake)
+ELSE(EXISTS ${CMAKE_MODULE_PATH}/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake)
+  # This one apparently doesn't have to actually exist, see OPTIONAL below.
+  SET(CMAKE_SYSTEM_AND_Fortran_COMPILER_INFO_FILE
   ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake)
+ENDIF(EXISTS ${CMAKE_MODULE_PATH}/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake)
 INCLUDE(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL)
 
 # This should be included before the _INIT variables are
-------------- next part --------------
# Settings for the GNU Fortran compiler (gfortran) under Cygwin
#
SET(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "")                     # -pic
SET(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-shared")       # -shared
SET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "")                # +s, flag for exe link to use shared lib
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG "")              # -rpath
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG_SEP "")          # : or empty

SET(CMAKE_Fortran_CREATE_SHARED_MODULE
  "<CMAKE_Fortran_COMPILER> <CMAKE_SHARED_MODULE_Fortran_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_MODULE_CREATE_Fortran_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} <OBJECTS> <LINK_LIBRARIES>")

SET(CMAKE_Fortran_CREATE_SHARED_LIBRARY
  "<CMAKE_Fortran_COMPILER> <CMAKE_SHARED_LIBRARY_Fortran_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> ${CMAKE_GNULD_IMAGE_VERSION} <OBJECTS> <LINK_LIBRARIES>")

SET(CMAKE_Fortran_LINK_EXECUTABLE
  "<CMAKE_Fortran_COMPILER> <FLAGS> <CMAKE_Fortran_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> -Wl,--allow-multiple-definition ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>")

# Initialize Fortran link type selection flags.  These flags are used when
# building a shared library, shared module, or executable that links
# to other libraries to select whether to use the static or shared
# versions of the libraries.
FOREACH(type SHARED_LIBRARY SHARED_MODULE EXE)
  SET(CMAKE_${type}_LINK_STATIC_Fortran_FLAGS "-Wl,-Bstatic")
  SET(CMAKE_${type}_LINK_DYNAMIC_Fortran_FLAGS "-Wl,-Bdynamic")
ENDFOREACH(type)
-------------- next part --------------
# Settings for the GNU Fortran compiler (gfortran) under MinGW
#
SET(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "")                     # -pic
SET(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-shared")       # -shared
SET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "")                # +s, flag for exe link to use shared lib
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG "")              # -rpath
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG_SEP "")          # : or empty

SET(CMAKE_Fortran_CREATE_SHARED_MODULE
  "<CMAKE_Fortran_COMPILER> <CMAKE_SHARED_MODULE_Fortran_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_MODULE_CREATE_Fortran_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} <OBJECTS> <LINK_LIBRARIES>")

SET(CMAKE_Fortran_CREATE_SHARED_LIBRARY
  "<CMAKE_Fortran_COMPILER> <CMAKE_SHARED_LIBRARY_Fortran_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> ${CMAKE_GNULD_IMAGE_VERSION} <OBJECTS> <LINK_LIBRARIES>")

SET(CMAKE_Fortran_LINK_EXECUTABLE
  "<CMAKE_Fortran_COMPILER> <FLAGS> <CMAKE_Fortran_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> -Wl,--allow-multiple-definition ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>")

# Initialize Fortran link type selection flags.  These flags are used when
# building a shared library, shared module, or executable that links
# to other libraries to select whether to use the static or shared
# versions of the libraries.
IF(MSYS OR MINGW)
  FOREACH(type SHARED_LIBRARY SHARED_MODULE EXE)
    SET(CMAKE_${type}_LINK_STATIC_Fortran_FLAGS "-Wl,-Bstatic")
    SET(CMAKE_${type}_LINK_DYNAMIC_Fortran_FLAGS "-Wl,-Bdynamic")
  ENDFOREACH(type)
ENDIF(MSYS OR MINGW)

# Create archiving rules to support large object file lists for static
# libraries.
IF(MSYS OR MINGW)
  SET(CMAKE_Fortran_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
  SET(CMAKE_Fortran_ARCHIVE_APPEND "<CMAKE_AR> r  <TARGET> <LINK_FLAGS> <OBJECTS>")
  SET(CMAKE_Fortran_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
ENDIF(MSYS OR MINGW)
-------------- next part --------------
SET(CMAKE_WINDOWS_OBJECT_PATH 1)
SET(CMAKE_LIBRARY_PATH_FLAG "-LIBPATH:")
SET(CMAKE_LINK_LIBRARY_FLAG "")
SET(WIN32 1)
IF(CMAKE_VERBOSE_MAKEFILE)
  SET(CMAKE_CL_NOLOGO)
ELSE(CMAKE_VERBOSE_MAKEFILE)
  SET(CMAKE_CL_NOLOGO "/nologo")
ENDIF(CMAKE_VERBOSE_MAKEFILE)

SET(CMAKE_Fortran_CREATE_SHARED_LIBRARY
 "link ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE}  /out:<TARGET> /dll  <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")

SET(CMAKE_Fortran_CREATE_SHARED_MODULE ${CMAKE_Fortran_CREATE_SHARED_LIBRARY})

# create a C++ static library
SET(CMAKE_Fortran_CREATE_STATIC_LIBRARY  "lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")

# compile a C++ file into an object file
SET(CMAKE_Fortran_COMPILE_OBJECT
    "<CMAKE_Fortran_COMPILER>  ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /object:<OBJECT> <FLAGS> /compile_only <SOURCE>${CMAKE_END_TEMP_FILE}")

SET(CMAKE_COMPILE_RESOURCE "rc <FLAGS> /fo<OBJECT> <SOURCE>")

SET(CMAKE_Fortran_LINK_EXECUTABLE
    "<CMAKE_Fortran_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> <OBJECTS> /exe:<TARGET> /link /force <CMAKE_Fortran_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")

SET(CMAKE_CREATE_WIN32_EXE /winapp)
SET(CMAKE_CREATE_CONSOLE_EXE )

IF(CMAKE_GENERATOR MATCHES "Visual Studio 6")
   SET (CMAKE_NO_BUILD_TYPE 1)
ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 6")
IF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR CMAKE_GENERATOR MATCHES "Visual Studio 8")
  SET (CMAKE_NO_BUILD_TYPE 1)
  SET (CMAKE_CONFIGURATION_TYPES "Debug;Release;MinSizeRel;RelWithDebInfo" CACHE STRING
     "Semicolon separated list of supported configuration types, only supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything else will be ignored.")
ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR CMAKE_GENERATOR MATCHES "Visual Studio 8")
# does the compiler support pdbtype and is it the newer compiler

SET(CMAKE_BUILD_TYPE_INIT Debug)
SET (CMAKE_Fortran_FLAGS_INIT "")
SET (CMAKE_Fortran_FLAGS_DEBUG_INIT "/debug:full")
SET (CMAKE_Fortran_FLAGS_MINSIZEREL_INIT "/Optimize:2 /Define:NDEBUG")
SET (CMAKE_Fortran_FLAGS_RELEASE_INIT "/Optimize:1 /Define:NDEBUG")
SET (CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT "/Optimize:1 /debug:full /Define:NDEBUG")

SET (CMAKE_Fortran_STANDARD_LIBRARIES_INIT "user32.lib")

# executable linker flags
SET (CMAKE_LINK_DEF_FILE_FLAG "/DEF:")
SET (CMAKE_EXE_LINKER_FLAGS_INIT " /INCREMENTAL:YES /force")
IF (CMAKE_COMPILER_SUPPORTS_PDBTYPE)
  SET (CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT "/force /debug /pdbtype:sept")
  SET (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO_INIT "/force /debug /pdbtype:sept")
ELSE (CMAKE_COMPILER_SUPPORTS_PDBTYPE)
  SET (CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT "/force /debug")
  SET (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO_INIT "/force /debug")
ENDIF (CMAKE_COMPILER_SUPPORTS_PDBTYPE)

SET (CMAKE_SHARED_LINKER_FLAGS_INIT ${CMAKE_EXE_LINKER_FLAGS_INIT})
SET (CMAKE_SHARED_LINKER_FLAGS_DEBUG_INIT ${CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT})
SET (CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO_INIT ${CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT})
SET (CMAKE_MODULE_LINKER_FLAGS_INIT ${CMAKE_SHARED_LINKER_FLAGS_INIT})
SET (CMAKE_MODULE_LINKER_FLAGS_DEBUG_INIT ${CMAKE_SHARED_LINKER_FLAGS_DEBUG_INIT})
SET (CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO_INIT ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO_INIT})


More information about the CMake mailing list