Chapter 7: Migrating Fortran Code
This chapter examines the process of migrating a Fortran code to the Microsoft® Windows® operating system from the UNIX environment. This migration may be to either the Windows subsystem or the Interix subsystem.
Fortran is relatively easy to port between platforms, largely because of the high degree of standardization between Fortran compilers and the types of applications for which Fortran is typically used.
The main difficulties with migrating Fortran code are often associated with either the integration of an application with other languages or its use of third-party libraries.
This chapter covers how you should:
Gather and analyze data regarding your Fortran application.
Select development tools and other resources for developing the Fortran code in the Windows environment.
Design and validate your Fortran migration.
Plan the migration of your Fortran application—specifically how to port the UNIX Fortran application to Windows using the Windows API.
Use Microsoft Visual Studio® .NET to debug the Fortran application.
On This Page
Data Gathering and Analysis
This section discusses the range of data you need to gather when you migrate Fortran code so that you can determine the best migration approach. The data that you must collect includes the following:
The Fortran level used (77, 90, or 95).
The graphical user interface (GUI) requirements.
Any required third-party libraries.
Whether the application provides any cross-language support.
The best development and build environment to use for the migration.
In addition, you must know how your Fortran code is being used, for example:
Is it a stand-alone application?
Does it expose interfaces for other languages?
Does it call interfaces in other languages?
Fortran is commonly used in computationally intensive applications. Often, this means that Fortran is used in loosely coupled, high-performance grid computing environments. Typically, distributed grid computing requires integration with dynamic scheduling and high-performance message passing. In most cases, Fortran modules are not a part of the core infrastructure services; they must therefore integrate with libraries that perform these functions.
It is also important to understand the target development environment for the Fortran migration. Possible target environments include:
Migration of the development environment from UNIX to Windows and the Windows application programming interface (API).
Continued development on UNIX with Windows as a cross-platform port.
Migration of the development environment from UNIX to a UNIX style development environment on Windows, such as Microsoft Interix.
These considerations must be addressed along with the actual source code migration.
Using Third-Party Libraries (Mixed Languages)
In addition to running as stand-alone modules, Fortran modules can call subprograms or be called by programs from other languages. This is true even for those Fortran modules that are contained within a dynamic-link library (DLL) or a static library.
This section describes mixed language compatibility with Fortran for both managed code and unmanaged code. Managed code is architecture-independent code that runs under the control of the Microsoft .NET common language runtime (CLR) environment. Unmanaged code is native, architecture-specific code.
Mixed-language applications can supply main programs and subprograms in the following formats:
Compiled objects (.obj) and static libraries (.lib)
.NET managed code assembly
When using mixed languages with Fortran, you must resolve the issues that are caused by differences in the following:
Calling conventions, which specify how arguments are moved and stored.
Naming conventions, which specify how symbol names are altered when placed in an .obj file.
The need to address differences in calling and naming conventions between Fortran and C or C++ is not unique to a migration from UNIX to Windows. The Windows platform offers a wide range of third-party libraries to perform functions that can eliminate the need of some of the UNIX-based custom code. The use of these types of third-party C or C++ libraries in Windows eases the overall migration task and is an advantage in migrating to Windows.
This section focuses on integrating Fortran with C and C++ libraries in the Windows subsystem. It begins by examining the default calling and naming conventions for Fortran and how these conventions work with typical Windows C and C++ libraries and with Windows APIs.
Table 7.1 lists the default calling and naming conventions for Fortran, C and C++, and Windows APIs.
Table 7.1. Fortran , C or C++ , and Windows API Calling and Naming Conventions
Procedure name in all uppercase
The procedure being called is responsible for removing arguments from the stack before returning to the caller.
Procedure name in all lowercase
The procedure doing the call is responsible for removing arguments from the stack after the call is finished.
Windows API (STDCALL)
Procedure name in all lowercase
The procedure being called is responsible for removing arguments from the stack before returning to the caller.
The next two sections discuss in detail the issues related to calling and naming conventions.
During a migration, a developer usually encounters both the C or C++ calling convention and the STDCALL convention. Some of the common development libraries can take care of some of the differences in calling conventions. Other libraries require explicit declarations.
Differences in calling conventions can be handled in a number of ways, including the use of:
The Fortran Interface statement.
C function declarations.
Modular code that uses Fortran libraries.
These are explained in the next sections.
The Fortran Interface Statement
You can use the Fortran Interface statement to transform Fortran calling conventions into C style conventions. The following example takes a call to the C function, CLibFunction, which calls a C function that passes an integer value. An alias attribute is used to take care of the difference in case and the extra underscore.
INTERFACE SUBROUTINE CLIBFUNCTION(I) !MS$ATTRIBUTES C, ALIAS:'_CLibFunction' :: CLIBFUNCTION INTEGER I END SUBROUTINE CLIBFUNCTION END INTERFACE
Attributes can be defined with the Interface statement to adjust the Fortran calling conventions so that they match the existing C libraries.
C Function Declarations
You can also use a combination of the C function declarations, function naming, and argument definitions to resolve calling convention differences. You can do this using the STDCALL or C options.
In C and C++ modules, you can specify the STDCALL calling convention by using the __stdcall keyword in a function prototype or definition. Windows procedures and API functions also use the __stdcall convention. The following example shows how a STDCALL function declaration handles stack calling conventions and suffixes in a manner similar to default Fortran conventions:
extern “C” void __stdcall FLIBUNCTION (int n);
This type of translation is especially useful when dealing with C++ name mangling (where the compiler adds characters to function names). Implementing the STDCALL convention tells the compiler that this function is not subject to C++ name mangling.
Alternatively, instead of changing the calling convention of the C code, using the Intel Fortran compiler, you can adjust the Fortran source code by using the C option. This is set with the ATTRIBUTES directive. For example, the following declaration assumes the subroutine is called with the C calling convention:
SUBROUTINE CALLED_FROM_C (A) !DEC$ ATTRIBUTES C :: CALLED_FROM_C INTEGER A
Another means of resolving calling convention differences is to use a compatibility layer to translate between Fortran and C or C++. Using this approach, C and C++ libraries can expose STDCALL type interfaces while actually calling the C or C++ routines using C calling conventions.
The strategy you use for third-party library integration also depends on whether the Fortran or C or C++ code can be modified. For example, introducing Fortran Interface statements is only a viable option if the developer can modify the Fortran source code. The same is true regarding changing of function declarations in C or C++ source code.
This makes the concept of a compatibility layer the most flexible solution. However, this solution requires you to develop and maintain additional source code.
As with most languages, modularity allows for easier cross-platform development. Because Fortran is most often used for high-performance computations, platform-specific routines may already exist in external, non-Fortran routines.
Even though Fortran is often isolated to computationally specific routines, platform-specific APIs, such as threading, synchronization, and GUI functions, can also be used in Fortran. The Windows APIs for threading, synchronization, and GUI functions are typically made available using Fortran modules.
For example, Fortran modules can exist for Windows GUI functions, threading, and OpenGL graphics. The Fortran modules encapsulate the C and STDCALL style functions to the Windows kernel and Windows API libraries. To enhance portability, platform-specific code should either be encapsulated in Fortran modules or through a call layer to C and C++ functions.
The Fortran module feature requires a Fortran 90 or later compiler.
Fortran GUI applications often use OpenGL for high-performance graphics. OpenGL provides a cross-platform API for GUI development with minimal platform-specific code requirements. In Windows, OpenGL is a C library and can be used either from a Fortran module or through a custom OpenGL GUI extraction layer.
Your migration choice will largely depend on whether the existing UNIX Fortran application extracts the GUI calls or uses a Fortran module. Either strategy can be migrated to Windows.
Names are an issue for external data symbols shared among parts of the same program as well as among external routines. Symbol names, such as the name of a subroutine, identify a memory location that must be consistent among all calling routines.
Parameter names (names given in a procedure definition to variables that are passed to it) are never affected.
Reasons for altering names include:
Case sensitivity (for example, in C and Macro Assembler (MASM)) or lack of case sensitivity (for example, in Fortran).
Name decoration (for example, in C++).
If naming conventions are not reconciled, the program cannot successfully link and you will receive an "unresolved external" error.
The following list summarizes how to reconcile names between languages:
All-uppercase names. If you call a Fortran routine that uses Fortran defaults and cannot recompile the Fortran code, then in C, you must use an all-uppercase name to make the call. Use of just the __stdcall convention in C code is not enough because __stdcall and STDCALL always preserve case in these languages. Fortran generates all-uppercase names by default and the C code must match it.
For example, these prototypes establish the Fortran function FFARCTAN(angle), where the argument angle has the ATTRIBUTES VALUE property:
In C: extern float __stdcall FFARCTAN( float angle );
All-lowercase names. If the name of the routine appears as all lowercase in C, naming conventions are automatically correct when the C or STDCALL option is used in the Fortran declaration. This is because any case, including mixed case, may be used in the Fortran source code, and the C and STDCALL options change the name to all lowercase.
Mixed-case names. If the name of a routine appears as mixed-case in C or MASM and if you cannot change the name, then you can resolve this naming conflict by using the Fortran ATTRIBUTES ALIAS option. ALIAS is required in this situation because Fortran will otherwise not preserve the mixed-case name.
To use the ALIAS option, place the name in single quotation marks exactly as it is to appear in the .obj file.
The following is an example for referring to the C function My_Proc on IA-32 systems:
!DEC$ ATTRIBUTES ALIAS:'_My_Proc' :: My_Proc
On Itanium-based systems, the same example would be coded without the leading underscore as:
!DEC$ ATTRIBUTES ALIAS:'My_Proc' :: My_Proc
To make this example work on both IA-32–based and Itanium-based systems, use the following:
!DEC$ ATTRIBUTES DECORATE,ALIAS:'My_Proc' :: My_Proc
Using Intel Fortran for Calling Non-Fortran Subprograms
A Fortran main program or subprogram can call a non-Fortran subprogram by using the Intel Fortran Compiler, supplied as one of the following:
Compiled object or static library. Name .obj or .lib in Project->Properties->Linker->Input->Additional Dependencies or on command line that links the application.
If creating a mixed-language solution in the Microsoft Visual C++® IDE, make the other project a Win32® static library and make it a dependent project of the Intel Fortran project. The library will get linked in automatically.
DLL. Supply import library, if available, as done in compiled object for static library.
If there is no import library, use Windows API routines LoadLibrary and GetProcAddress and call the procedure through an integer pointer.
.NET managed code assembly. Use the Intel Fortran Module Wizard to generate the interfaces for routines in the assembly.
A Fortran subprogram can be called by a non-Fortran main program or subprogram as a compiled object, static library, or dynamic-link library, depending on the capability of the calling language. When calling Fortran code from a .NET managed code assembly, the Fortran code must be in a DLL.
Note Additional information on the Intel Fortran compiler is available at
Integrating Fortran with POSIX Applications
The Fortran application that you are migrating may be required to integrate with other POSIX-style applications. In this situation, the target Windows environment can be either the Windows POSIX subsystem (Interix), or a UNIX emulator running on the Windows subsystem. Microsoft Interix is the full-featured POSIX subsystem on Windows. MKS NuTCRACKER and Cygwin are examples of UNIX emulators.
The Fortran considerations for using either the Interix POSIX subsystem or a UNIX emulator are the same as for C or C++ migrations.
Note As of the time of publication, the GNU Fortran 77 compiler, f77, is the only Fortran compiler available for Interix.
Development Tools and Resources
This section provides you with information on the various development tools and resources such as compilers and IDEs for developing the Fortran code in the Windows environment. Microsoft supplies the GNU Fortran 77 compiler with the Interix subsystem. Microsoft does not supply or sell a Fortran compiler for Windows. For migrations that require Fortran 90 or Fortran 95 features, a third-party Fortran compiler, such as the Intel Visual Fortran compiler or the Lahey/Fujitsu Fortran compiler, is required to target Windows.
When you migrate Fortran applications, you must ensure that you implement the necessary development tools, including a source-code control system and build analysis and management tools. You should also consider your cross-platform build and debug environments. The Fortran version that you use for development must be compatible with the other development tools that you use during the migration.
For example, if your migration targets the Microsoft Visual Studio® .NET 2003 development system, your Fortran compiler should integrate with Visual Studio .NET 2003. The Intel Fortran Compiler 8.1 can plug into the Visual Studio .NET 2003 development environment.
Design and Validation
When you migrate a Fortran application from UNIX to Windows, the design and capabilities of the Fortran code must be an integral part of the design of your migrated application. This section will help you to estimate the effort required for migration and to identify potential risks in the Fortran migration. Considerations such as performance, library interoperability, and feature set can determine the overall success of the project.
Sizing the Fortran Migration
The effort required to conduct a Fortran migration depends largely on the answers to the following questions:
Is the code modular?
Will platform-specific code need migration within Fortran?
What third-party libraries will Fortran code need and are these compatible with Windows?
Is the Fortran module calling any non-Fortran language function/module?
What is the version of the Fortran compiler?
Is GUI or graphics support required?
Do feature or function abstraction layers already exist in UNIX?
Because it is likely that the features and functions needed for a Windows migration already exist on UNIX, answers to these questions might already be available. If the code is already modular with feature or function abstraction layers, the code itself will move easily across as a port to Windows. In this case, the bulk of your effort will be spent in choosing any required third-party libraries, the cross-language calling conventions, and the integrated development environment (IDE) tools.
Assessing and Mitigating Risk
Fortran adds complexity and, consequently, risk to a migration because of the following reasons:
You might require a third-party Fortran compiler.
You might need call-level integration between the Fortran and C or C++ code.
You will need a cross-language build and debug strategy for Windows.
You can mitigate Fortran migration risks by:
Defining the Windows development environment, including the Fortran compiler and your integration strategy for C or C++ code and third-party libraries.
Implementing modularity of the Fortran code and putting platform-specific features into a C or C++ compatibility layer. This will enhance the capability of the code to migrate from UNIX to Windows and is essential if the application needs to target both the UNIX and Windows platforms.
Identifying the tools for building and debugging Fortran code and other interfacing languages like C or C++ in the Windows environment.
This section describes how you should plan a Fortran migration and discusses several migration strategies. In particular, this section provides information about how to scope a Fortran migration to Windows using the Windows API.
Scoping the Fortran Migration
At first glance, an ANSI Fortran application migration can have most (if not all) of the same migration combinations as a C or C++ migration. A Fortran application can:
Have a GUI for user interaction.
Use platform-specific features.
However, most Fortran applications perform specialized functions where the Fortran language is particularly suitable. For example, Fortran is particularly suited as a language for computationally intensive mathematical operations. Other languages, such as C and C++, provide more widely used features and libraries for such things as process and thread support and GUI features. For this reason, Fortran source code often performs only the computationally intensive functions in an application, leaving the process management and user interaction to C and C++.
Using Fortran in this manner removes most of the platform-specific issues from an ANSI Fortran migration. This means that in most cases, you can port the Fortran code of an application from UNIX to the Windows API with minimal changes. The C or C++ code usually requires the majority of the migration effort.
Porting Fortran to Interix
Before rewriting a Fortran application for Windows, you should consider other migration strategies. Porting to Interix represents just one possible strategy.
For porting UNIX style source to Interix, the GNU Fortran 77 compiler is provided. As the level is Fortran 77, applications that require Fortran 90 support, such as module support, cannot be ported to Interix. In addition, because POSIX subsystem libraries cannot be mixed with Windows subsystem libraries, Windows API versions of C and C++ that require Fortran libraries cannot use them from Interix. This leaves stand-alone Fortran 77 applications that interoperate with stdin and stdout as the best candidates for a UNIX style port to Interix.
Porting UNIX Fortran Source to Windows Using the Windows API
This section describes how to port Fortran code to Windows. Most Fortran migrations are a port, not a rewrite, to Windows. However, Fortran migrations involve migrating and integrating other language modules in the application. Techniques and strategies for using C and C++ tools and source from Fortran are required to complete the application migration.
For this purpose, most of the discussion in this section focuses on how to integrate Fortran code with C and C++ modules or libraries on the Windows platform.
Using C or C++ Libraries or Fortran Modules
Fortran applications can access cross-platform libraries either by using C and C++ libraries or through Fortran modules (available with Fortran 90 and later versions). If the cross-platform libraries are written in C or C++, there is little (if any) difference between this type of strategy and a port-to-Windows strategy. Currently, there are few third-party Fortran module suppliers. This is because of the limited market for Fortran and the fact that Fortran compilers are provided by third parties. Microsoft does not provide a Fortran compiler. Fortran modules are typically supplied by the compiler vendor or are created in-house.
Porting Fortran to Windows
It is possible to rewrite an application written entirely in Fortran to target Windows. The key task here is to identify how platform-specific features are implemented in Fortran. This is typically done with Fortran modules. If this is the case, you must identify or develop a corresponding Fortran module for each feature on Windows that exists on the source platform. For example, if an OpenGL module and threading module are used on UNIX, you must identify or develop a corresponding OpenGL and threading module to use on Windows.
Debugging Fortran Using Visual Studio .NET 2003
Although your Fortran application must be developed in an environment outside Visual Studio .NET 2003, you may need to include your Fortran code as a library or object module in a C or C++ project in Visual Studio .NET 2003. In most cases, this requires the Visual Studio .NET 2003 debugger to step through the Fortran code, as well as the C and C++ codes. This section explains how you can integrate Fortran libraries and object modules in Visual Studio .NET 2003 projects and debug the Fortran code when you debug other portions of your project.
Before debugging, you may need to include Fortran modules or libraries in projects that contain C and C++ source files. Although Microsoft does not provide a Fortran compiler with Visual Studio .NET 2003, you can include Fortran modules in Visual Studio .NET 2003 projects. To do this, compile the Fortran library or Fortran module with an option that produces a program debug database. Visual Fortran provides this option with the -Zi compiler option. This is similar to the process you use to create a program debug database for C and C++ programs. This creates a file with the .pdb extension that contains the debug symbols.
After you have created a debug version of your Fortran module or library, you can include it in a C or C++ project. The easiest way to do this is to add the debug version of the Fortran project as input for the Visual Studio linker.
To add the Fortran project
On the Project menu, click Properties.
In the Configuration list, click Debug.
In the Platform list, click Win32.
Click the Linker tab.
In the Input box, type the name of the Fortran object module or library you want to include.
Alternatively, you can use the Intel Visual Fortran compiler within Visual Studio .NET 2003 to develop Fortran applications, including static library (.lib), dynamic-link library (.dll), and main executable (.exe) applications. You can build your source code into several types of programs and libraries, either using Visual Studio .NET 2003 or working from the command line.
Note Use the IDE to build applications for IA-32 Windows-based systems only.
For building a Fortran project using Visual Studio .NET 2003, you need some additional settings. The following procedures describe the settings required in Visual Studio .NET 2003.
You must enter a search path so that the linker can find the module or library you added. The path must include the current working directory and the directories specified in the Options dialog box.
You can set the path and library and include directories for your Intel Fortran project environment on Visual Studio .NET 2003.
To add a new folder to the search path
On the Tools menu, click Options.
Click Intel Fortran in the list on the left of the dialog box.
In the General category, specify the directories in which the Visual Studio project system should look for files, as follows:
Executables. Specify the directories to be searched for executable files. (Works like the PATH environment variable.)
Libraries. Specify the directories to be searched for libraries. (Works like the LIB environment variable.)
Includes. Specify the directories to be searched for include files. (Works like the INCLUDE environment variable.)
Visual Studio .NET 2003 does not provide an option to specify the path for the .pdb file for your Fortran module. Therefore, you must place the .pdb file in the same directory as the library or object module you want to include.
You can also add a Fortran module or library directly to the project.
To add a Fortran object module or library directly
On the Project menu, click Add New Item. The Add New Item dialog box appears.
In the Templates tab, select .obj or .lib, depending on whether you need to insert an object module (.obj) or library (.lib).
Enter the file and the path for the Fortran object module or the library you want to add from the Location box or the browser.
Now you are ready to start debugging. You can start the debugger and step through code in either the C or C++ source or the Fortran source.
You can also debug the binaries created with the Zi compiler option using other Microsoft debug tools, such as WinDbg.
You may need to include a Fortran object module or library in a Visual Studio .NET 2003 project where a debug version of the object module or library is not available, or you may not need to include the Fortran routines in your debug session. If you do not need to debug the Fortran modules in a Visual Studio .NET 2003 project, you can include the release versions of either the object module or library as part of the link. You can continue to debug the C or C++ code. However, the debugger will not step into the Fortran source when a Fortran routine is entered. To accomplish this, include the release version of the Fortran object module or library in the All Configurations section of the Project Settings dialog box.
If you must include Fortran code as part of your debugging, remember to include the release versions of the Fortran object module or library in the Win32 Release section of the Project Setting dialog box.
Summary of Fortran Code Migration
The primary tasks in a Fortran code migration are focused on integration with libraries and the development environment. The actual Fortran code can usually be migrated or ported with little or no changes, provided that the level of Fortran compiler on the source platform is the same as the target platform. For example, if your application was developed on the source platform using Fortran 90, the target platform also needs a Fortran 90 compiler or Fortran 90 compatibility mode.
Issues related to source files and source control migration from UNIX to Windows are similar for Fortran because they are for C and C++. These issues are covered in Chapter 4, “Planning Phase: Setting Up the Development and Test Environments” of Volume 1: Plan of this guide.