[CMake] Fortran-C mixed code
Radu Serban
radu at llnl.gov
Thu Jan 18 13:24:00 EST 2007
Alan W. Irwin wrote:
> On 2007-01-12 12:42-0800 Radu Serban wrote:
>
>> I'm attempting to use cmake to configure a package containing both
>> Fortran (F77) and C source code (as an alternative to the current
>> build system which uses autoconf+libtool) but I couldn't figure out
>> how to properly do that.
>
> Have you considered splitting your library into a fortran-only library
> and a
> C-only library? Autotools tries to support mixing fortran- and C-compiled
> objects in the same library (using the AC_F77_LIBRARY_LDFLAGS macro and the
> resulting FLIBS), but we could never get that to work reliably on all
> platforms for PLplot. Thus, we ended up splitting our libraries into
> fortran-only and C-only when we were still building with autotools, and we
> have continued that approach now we have migrated to cmake. We didn't have
> to do anything special to get this approach to work. Just use the
> appropriate ADD_LIBRARY command for each library, and use
> TARGET_LINK_LIBRARIES to establish the dependencies between them, and the
> result seems to build fine on all platforms.
>
> Alan
Hi Alan,
Splitting the library into two is unfortunately not applicable to my case (see
below why).
In my initial post I had raised 3 issues (determining the F77 intrinsic and
run-time libraries, using a C compiler to link an executable from an object
created from a Fortran source and a C library, and determining the Fortran
compiler's name mangling scheme).
The first two issues are relevant only if the C library is actually built using
a C++ compiler. However, I realized that cmake will stop with an error if I set
the environment variable CC to, say, g++ before invoking cmake on my project
(#error "The CMAKE_C_COMPILER is set to a C++ compiler"). As such, I can always
be sure that a C++ compiler will not be used to create the library from the C
sources and using the Fortran compiler to link will work just fine (and the F77
intrinsic and run-time libraries will not be needed).
But knowing the Fortran name mangling scheme is still crucial (if interested,
see below why). For now I rely on the user to provide the case (lower or upper)
and number of appended underscores (none, one, or two) which determine it. The
defaults I provide (lower case with one underscore) is probably the most common
one, but I'd be much happier if I could automatically determine it at
configuration time... Any suggestions?
Finally, I'm now wondering why cmake will not allow using a C++ compiler on C
sources. Sure, one must be careful in conditionally including the appropriate
wrappers in the header files to allow C++ usage, but I don't see why cmake would
absolutely forbid this. Issuing a warning may be appropriate, why an error? Am I
missing anything?
--Radu
P.S. Here's why knowing the Fortran name mangling scheme is important for us.
We distribute a library (CVODE) for solving ordinary differential equations
(ODE). CVODE is part of an entire suite of solvers, but that is irrelevant for
this discussion. A user who wants to use CVODE to solve a given ODE problem must
then provide both the main function and an additional function which defines the
ODE right-hand side (the RHS function), i.e. the function f in y'=f(t,y). The
user then links these two functions together with the CVODE library into their
executable. Therefore, the following is a typical calling chain:
user's C main ->
CVODE C library function cv_solve ->
user's C RHS function f (of type CVRhsFn)
The solver is written all in C, so building the library with cmake is no
problem. However, for Fortran users, i.e. users who want to provide the main and
f functions as Fortran sources (the RHS function in this case must have the
fixed name FCVFUN), we also provide an Fortran-C interface library. This second
library, FCVODE, is also all written in C. The above calling chain now becomes:
user's Fortran PROGRAM ->
FCVODE C library function FCVSOLVE ->
CVODE function cv_solve ->
FCVODE C library function fcv_RhsWrapper (of type CVRhsFn; wrapper around
FCVFUN) ->
user's Fortran FCVFUN
For our library sources to work unmodified regardless of the Fortran compiler,
the FCVODE library includes a configuration header files which defines function
names based on the Fortran name mangling scheme. For example, if the scheme is
lower case with one appended underscore, we have
#define FCV_SOLVE fcvsolve_
#define FCV_FUN fcvfun_
and I can use FCV_SOLVE to declare and define the user-callable FCVODE solver
function while the implementation of the FCVODE library function fcv_RhsWrapper
always calls FCV_FUN(...), etc.
More information about the CMake
mailing list