[CMake] Extension proposal: CheckFortranFuinctionExists.cmake
Arjen Markus
arjen.markus at wldelft.nl
Thu Jun 26 00:19:27 EDT 2008
> On 2008-06-25 16:32+0200 Bernd Schubert wrote:
>
>> No, it is really no problem to link fortran libraries and to call their
>> functions. It is onkly a bit nasty sometimes to write the proto types of
>> the
>> blas/lapack functions, since nobody seems to have created a complete set
>> of
>> these, afaik. For real number crunching one also uses the intel/amd or
>> goto
>> libraries and there is always only one library of these, for both C and
>> Fortran (afaik, these optimized libraries are also not written in
>> fortran
>> anymore, they just have this stupid interface to be compatible with
>> fortran.
>> The other issue with fortran libraries is to figure out, how these have
>> been
>> compiled (additional underscores, etc).
>
> You have described issues which illustrate and support my point. They may
> be
> considered fairly trivial on one fixed platform but become important if
> you
> are trying to make a multi-platform build system. For example, what do
> you
> do about the underscore issue if you are testing the linking of C code
> with
> the fortran blas library? On one platform you will have to test sgemm, on
> another you will have to test sgemm_. These cross-platform build-system
> issues all disappear if you test C/C++ code against the C version of blas.
>
>>
>> On the other hand, cblas even has a slightly different interface than
>> nativ
>> blas, so without changing the existing code it is not suitable for
>> linking.
>>
>
> Changing your existing code once to link to cblas may be a smaller price
> to
> pay. If your existing C/C++ code linked to the fortran BLAS library is to
> work on multiple platforms, what do you do about the cross-platform issue
> involving underscores? You will end up doing a lot of extra work to
> support
> the platform variations that is not required if you link to the C version
> of
> BLAS.
>
With regards to the differences in calling and naming conventions
between Fortran and C, I recently posted a program on the comp.lang.fortran
newsgroup to solve that issue automatically, at least for the platforms
I have access to. It is part of my Ftcl project, the combination of Fortran
and Tcl - http://ftcl.sf.net. I post it below, as it may help solving the
current issue.
The idea is very simple:
Let the linker decide which version of a C routine will be called
by the Fortran program and let that version write its properties
to a header file.
Regards,
Arjen
----- probe.f90 -----
! probe.f90 --
! Try and identify the Fortran naming and calling convention
! - part of Ftcl
!
! Note:
! This is the Fortran part of a program that uses a few tricks
! to determine:
! - The naming convention for the Fortran compiler (including
! the current options that influence this convention).
! The result will be:
! - One of FOR_ALL_LOWER, FOR_ALL_CAPS, FOR_UNDERSCORE or
FOR_DBL_UNDERSCORE
! will be defined. These are the most common naming conventions
! - The macro IN_BETWEEN is defined or undefined so that string
! arguments can be properly passed
! - The macro FOR_CALL is defined to capture the correct calling
! convention vis-a-vis stack clean-up
! - The values of these macros are stored in a file "ftcl_conventions.h"
!
! If the program fails, it will need to be expanded, as that is an
! indication that this particular combination of Fortran and C
! compilers is not yet supported.
!
program probe
character(len=7) :: first = 'Fortran'
character(len=3) :: second = 'Tcl'
call probe_c( first, second )
end program probe
----- probe_c.c -----
/* probe_c.c --
* Companion to the file probe.f90. Together they form a program
* that will write a header file with the right macros for
* setting up the interface between Fortran and C.
*
*/
#include <stdio.h>
#include <stdlib.h>
/* probe_c --
Plainly named version
*/
void probe_c( char *first, int len_first, char *second, int len_second ) {
FILE *outfile ;
outfile = fopen( "ftcl_conventions.h", "w" ) ;
fprintf( outfile, "#define FOR_ALL_LOWER\n" ) ;
fprintf( outfile, "#define FOR_CALL\n" ) ;
/* If hidden length argument in between, then len_first must be 7 */
if ( len_first == 7 ) {
fprintf( outfile, "#define IN_BETWEEN\n" ) ;
} else if ( (int) second == 7 ) {
fprintf( outfile, "#undef IN_BETWEEN\n" ) ;
} else {
fprintf( stderr, "Unknown expected calling convention - assuming
NOT IN_BETWEEN!\n" ) ;
fprintf( outfile, "#undef IN_BETWEEN\n" ) ;
}
fclose( outfile ) ;
}
/* PROBE_C --
All capitals version - possibly __stdcall too
*/
#ifdef _MSC_VER
#define FOR_CALL __stdcall
#else
#define FOR_CALL
#endif
void FOR_CALL PROBE_C( char *first, int len_first, char *second, int
len_second ) {
FILE *outfile ;
outfile = fopen( "ftcl_conventions.h", "w" ) ;
fprintf( outfile, "#define FOR_ALL_CAPS\n" ) ;
#ifdef _MSC_VER
fprintf( outfile, "#define FOR_CALL __stdcall\n" ) ;
#else
fprintf( outfile, "#define FOR_CALL\n" ) ;
#endif
/* If hidden length argument in between, then len_first must be 7 */
if ( len_first == 7 ) {
fprintf( outfile, "#define IN_BETWEEN\n" ) ;
} else if ( (int) second == 7 ) {
fprintf( outfile, "#undef IN_BETWEEN\n" ) ;
} else {
fprintf( stderr, "Unknown expected calling convention - assuming
NOT IN_BETWEEN!\n" ) ;
fprintf( outfile, "#undef IN_BETWEEN\n" ) ;
}
fclose( outfile ) ;
}
/* probe_c_ --
Single underscore
*/
void FOR_CALL probe_c_( char *first, int len_first, char *second, int
len_second ) {
FILE *outfile ;
outfile = fopen( "ftcl_conventions.h", "w" ) ;
fprintf( outfile, "#define FOR_UNDERSCORE\n" ) ;
fprintf( outfile, "#define FOR_CALL\n" ) ;
/* If hidden length argument in between, then len_first must be 7 */
if ( len_first == 7 ) {
fprintf( outfile, "#define IN_BETWEEN\n" ) ;
} else if ( (int) second == 7 ) {
fprintf( outfile, "#undef IN_BETWEEN\n" ) ;
} else {
fprintf( stderr, "Unknown expected calling convention - assuming
NOT IN_BETWEEN!\n" ) ;
fprintf( outfile, "#undef IN_BETWEEN\n" ) ;
}
fclose( outfile ) ;
}
/* probe_c__ --
Double underscore (for Fortran names that have an embedded underscore)
*/
void FOR_CALL probe_c__( char *first, int len_first, char *second, int
len_second ) {
FILE *outfile ;
outfile = fopen( "ftcl_conventions.h", "w" ) ;
fprintf( outfile, "#define FOR_DBL_UNDERSCORE\n" ) ;
fprintf( outfile, "#define FOR_CALL\n" ) ;
/* If hidden length argument in between, then len_first must be 7 */
if ( len_first == 7 ) {
fprintf( outfile, "#define IN_BETWEEN\n" ) ;
} else if ( (int) second == 7 ) {
fprintf( outfile, "#undef IN_BETWEEN\n" ) ;
} else {
fprintf( stderr, "Unknown expected calling convention - assuming
NOT IN_BETWEEN!\n" ) ;
fprintf( outfile, "#undef IN_BETWEEN\n" ) ;
}
fclose( outfile ) ;
}
More information about the CMake
mailing list