Building OpenGL capable Fortran apps on Windows

This post is about compiling a mature Windows Fortran application with OpenGL and the open source compiler gFortran. You can find a link to the GitHub repository with full source at the end of the article. I've documented these steps as an aide-memoire and to help others.

An example of the Fortran compiled OpenGL samples

An example of the Fortran compiled OpenGL samples, the jerky nature of the image is due to the GIF encoding. The original runs very smoothly.

Why build a Windows app in Fortran?

I'm working with a friend on updating his particle physics software which is written in C++ and Fortran. I've jokingly said that some of the software is older than me and it's quite possible that it is, having been started in the late 60's ( I was powered up in 1970 ).

There is so much value in the source code that has been built up over the years that a rewrite is not feasible (we'd probably break a lot of functionality and it's not a small codebase).

The problem is that to compile a 64 bit version we needed to upgrade to a 64 bit capable compiler (the open source gfortran compiler) as the tools that were used previously were no longer stable or well supported. Both the C++ and Fortran source used compiler specific language extensions which didn't prove to be too much of an issue. The main problem was that the old compiler had built in support for OpenGL that wasn't syntax compatible with gFortran.

Windows has OpenGL support built in but developing Fortran apps that use it can be a problem as the most recent Fortran OpenGL wrappers are normally used under Linux and they need some tweaking to work under Windows.

Walkthrough - installing Fortran and building the samples

In summary, the steps required to prove you have a working Fortran compiler and OpenGL setup are;

  1. Set up your Windows Fortran development environment.
  2. Download the f03gl Fortran OpenGL wrapper source.
  3. Locate / install the Windows OpenGL libraries.
  4. Compile the OpenGL wrappers.
  5. Compile the samples.
Set up your Windows Fortran development environment

Ideally, we'd like an up to date Fortran compiler.

I recommend using the MSYS2 project which gives you an up to date set of open source compilers (gcc, gfortran etc.) for Windows. MSYS2 helps you keep these up to date and gets rid of the hassle of having to compile your own compiler (I understand why Linux does this, but it's a major barrier to entry). I'm assuming that being a developer, you'll be running a 64 bit OS (we can build both 32 and 64 bit applications from this).

I've assumed default paths etc. for below.

  1. Go to the MSYS2 project and download the 64 bit version.
  2. Start a 64 bit prompt by clicking on the shortcut to c:\msys64\mingw64.exe
  3. Keep running pacman -Syuu until everything is up to date.
  4. Exit the prompt and start a new one to make sure you get the refreshed tools.
  5. Run pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain mingw-w64-i686-cmake mingw-w64-x86_64-cmake.
  6. You should now have C:\msys64\mingw32\bin and C:\msys64\mingw64\bin, both containing toolchains for 32 and 64 bit Fortran.
  7. Start a command prompt for both 32 and 64 bit and compile a simple 'Hello World' program via gfortran h.f90 -o hello32.exe or gfortran h.f90 -o hello64.exe.

      program hello
      print *, "Hello World in Fortran!"
      end program hello
    
  8. Check that the executables generated run and show correctly as 32 or 64 bit in the Task Manager. You will have to run the executable from the same directory you compiled them (the bin folders above) in order to pick up the support libraries unless you put it in your path. If you do add both compiler directories to your path, you'll need to differentiate the version of gfortran you call by using one of the following;

    a. 32 bit - i686-w64-mingw32-gfortran.exe
    b. 64 bit - x86_64-w64-mingw32-gfortran.exe
    

That should be your development environment set up.

These notes have been cobbled together from;

Assemble the OpenGL components
  1. Create a new directory (we'll call it Bob just to be different, you can call it anything you want, it does not matter) for containing our OpenGL build and underneath that directory, create two folders named x86 and x64. In those folders create four more sub folders named bin, dll, obj and lib. They should look somewhat similar to the following;
  2. You'll need the FreeGlut binaries which can be downloaded from http://www.transmissionzero.co.uk/software/freeglut-devel/ .
    • Extract the zip contents to a new folder named freeglut in the root of the 'Bob' folder you created.
    • Copy the 32 and 64 bit dll and lib files from freeglut to the relevant x86\x64 lib and dll folders.
  3. Find the 32 and 64 bit versions of OpenGL32.lib on your system (both architectures are named the same, but the 64 bit version should be in a folder with 64 somewhere in the name). If you can't find these, you'll need to install the Windows Platform Software Development Kit which is freely available from Microsoft and updated frequently, hence my not linking to it here. You may already have it installed if you have development tools on your machine.
    • The way I find these files is to run an admin cmd prompt and from the root of the drive use dir /s opengl32.lib. If you get too many files listed, then pipe the output to a text file by appending >openglfiles.txt and go through that manually to find the latest versions.
    • To be sure you know which is 32 and which is 64, use - dumpbin /headers opengl32.lib | findstr machine from a command prompt (dumpbin is from the Microsoft SDK). If you use the 32 bit lib on a 64 bit compiler or vice-versa, you'll get linker errors.
    • Once you have the binaries located, copy them to the relevant x86 and x64 lib and DLL sub directories.
  4. Repeat previous step for glu32.lib.
  5. Download the OpenGL Fortran wrappers and sample source at http://www-stone.ch.cam.ac.uk/pub/f03gl/index.xhtml, extract to the Bob directory you chose earlier. This project has done the hard work of defining the C standard interfaces for calling OpenGL from Fortran. However, it won't compile for 32 bit versions without modification due to x86 name mangling. See the next step for how to overcome this.
  6. The OpenGL samples will fail to build for 32 bit and need the STDCALL hints providing to the compiler. For example 'glutMainLoop' cannot be found by the linker initially because the symbol name is mangled according to STDCALL. Changing the definition of glutMainLoop to the following in the Fortran Module (OpenGL_freeglut.f90) that calls the API will remove this from the list of compiler errors (I've done a lot of these for the samples, but not all. You can find the code at the GitHub link below);

    PUBLIC glutMainLoop
    INTERFACE
    SUBROUTINE glutMainLoop() BIND(C,NAME="glutMainLoop")
    IMPORT
    #ifdef x86
    !GCC$ ATTRIBUTES stdcall :: glutMainLoop
    #endif
    END SUBROUTINE glutMainLoop
    END INTERFACE
    
  7. Open a command prompt at the Bob directory you chose earlier and compile the OpenGL samples using BuildSamples32.bat and BuildSamples64.bat (these batch files are also in the GitHub source).

  8. The samples should now be available as compiled executables and can be run from the x86\bin and x64\bin folders.

For some reason I have not had time to look into, the 32 bit versions do not stick to proper timings and run too fast. I suspect that this is a problem with a DWORD being used instead instead of a WORD somewhere.

Screen captures

All of the samples below have been compiled with gFortran and OpenGL bindings on Windows 10.

Teapot Shadow cube Function plot Star field Sphere

Source

The source code (you'll still need to find the libraries as outlined above as these may be copyrighted, but freely available).

Due to an ever present workload, I'm unable to answer questions but may be available for consulting.

comments powered by Disqus

Ryan O'Neill

Mostly about tech, working for myself and my thoughts.

Ludlow, Shropshire, UK