<< zur Fortran-Startseite
< Anhang D: Quellcodedokumentation Anhang F: Photran >



Einleitung

Bearbeiten

Hier wird keine Einführung in die Verwendung und Syntax von make- und config-Tools geboten, sondern nur kurz auf einige Spezialitäten hingewiesen, die bei den ersten Einsatzversuchen derartiger Werkzeuge im Zusammenhang mit Fortran zu beachten sind.

Grundsätzlich kann bei der Erstellung von Makefiles und Konsorten eine ähnliche Vorgehensweise wie bei konventionellen C-Programmen gewählt werden. Es ist bei Fortran-Programmen jedoch zu bedenken, dass bei Verwendung von Modulen mod-Dateien generiert werden (ab Fortran 90). Diese mod-Dateien sind in weiterer Folge für das Kompilieren von moduleinbindenden Quellcodedateien und den Linkvorgang von entscheidender Bedeutung. Somit ist bei hierarchisch verzweigten Quellcodeverzeichnisbäumen Obacht zu geben, dass jeweils auch Zugriff zu diesen mod-Dateien gegeben ist. Dies kann geschehen durch

  • geeigneten Aufbau der Makefiles,
  • durch Verwendung von Tools, die solche Abhängkeiten automatisch auflösen
  • oder auch durch explizite Bekanntgabe der entsprechenden Pfade an Compiler und Linker.

Explizite Bekanntgabe von Modulpfaden

Bearbeiten

gfortran

Bearbeiten

Standardmäßig werden include- und mod-Dateien im aktuellen Verzeichnis gesucht. Die Suche kann aber mit folgendem Compilerschalter auf andere Pfade ausgedehnt werden:

  • -I...: Suchpfad für
    • include-Dateien
    • mod-Dateien
erweitern.

Standardmäßig werden mod-Dateien in das aktuelle Verzeichnis geschrieben. Dieses Verhalten kann mit folgendem Schalter geändert werden:

  • -J...: Legt Verzeichnis fest, in das die mod-Dateien geschrieben werden, gleichzeitig auch Suchpfad für mod-Dateien.
(Alias für -M... um Konflikte mit bisherigen GCC-Optionen zu vermeiden)

Standardmäßig werden include- und mod-Dateien im aktuellen Verzeichnis gesucht. Die Suche kann aber mit folgendem Compilerschalter auf andere Pfade ausgedehnt werden:

  • -I...: Suchpfad für
    • include-Dateien
    • mod-Dateien
erweitern.

Auch der g95-Compiler kennt einen -M-Schalter. Dieser hat aber eine komplett andere Bedeutung als beim gfortran-Compiler. Stattdessen gibt es beim g95-Compiler den Schalter:

  • -fmod=...: Legt Verzeichnis fest, in das die mod-Dateien geschrieben werden, gleichzeitig auch Suchpfad für mod-Dateien.
  • -I...: Suchpfad für
    • include-Dateien
    • mod-Dateien
erweitern.
  • -module ..: Legt Verzeichnis fest, in das die mod-Dateien geschrieben werden, gleichzeitig auch Suchpfad für mod-Dateien.

Sun f90/f95

Bearbeiten
  • -M...: Fügt den angegebenen Pfad zum Modulsuchpfad hinzu.
  • –moddir=...: mod-Dateien werden in das angegebene Verzeichnis geschrieben, gleichzeitig auch Suchpfad für mod-Dateien.

GNU Make

Bearbeiten

GNU Make erkennt derzeit leider nur FORTRAN 77-Dateien mit der Endung .f automatisch. Für "free source form"-Fortran-Programme sind daher einige vorbereitende Arbeiten nötig, um dann auch die Vorteile (und Nachteile) der impliziten Anwendung von "Pattern Rules" genießen zu dürfen. Werden alle Makeschritte für Fortran-Dateien explit vorgegeben, dann kann man sich dies natürlich sparen.

Ein einfaches Beispiel

Bearbeiten

Es sei ein einfaches Beispiel gegeben, das eine FORTRAN 77-, eine Fortran 2003- und eine C-Datei enthält. Diese Dateien liegen im selben Verzeichnis.

Quellcode-Dateien

Bearbeiten

main.f03:

Fortran 2003 (oder neuer)-Code
! Das Hauptprogramm
program main
  implicit none 

  interface
    function addition( a, b ) bind( c )
      use, intrinsic :: iso_c_binding
      real( kind = c_float ), value :: a
      real( kind = c_float ), value :: b
      real( kind = c_float )        :: addition
    end function addition
    
    subroutine sub()
    end subroutine sub
  end interface

  call sub()
  write (*,*) addition( 2.5, 3.3 )
  
! Ausgabe:  
!    Summe =
!      5.8  
end program main

func.c:

Programmcode
/* Addiere zwei Zahlen */
float addition(float a, float b)
{
  return (a + b);  
}

sub.f:

0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  
12345678901234567890123456789012345678901234567890123456789012345678901234567890
C  Eine einfache FORTRAN 77-Subroutine          
      SUBROUTINE SUB
      WRITE( *, * ) 'Summe ='   
      END
12345678901234567890123456789012345678901234567890123456789012345678901234567890
0   . |  1    .    2    .    3    .    4    .    5    .    6    .    7 |  .    8  

Explizite Vorgabe der Makeschritte

Bearbeiten

Makefile:

FC = gfortran        # oder g95, ifort, ...

prog: main.o func.o sub.o
	$(FC) -o $@ $^

main.o: main.f03
	$(FC) -c $^

func.o: func.c
	$(CC) -c $^
	
sub.o: sub.f
	$(FC) -c $^	

Nutzung von "Pattern Rules"

Bearbeiten

Makefile:

FC  = gfortran      # oder g95, ifort, ...

%.o: %.f03
	$(FC) -c $<

prog: main.o func.o sub.o
	$(FC) -o $@ $^

Die Generierung der Objektdateien aus den Quellcodedateien geschieht hier implizit. Für C- und FORTRAN 77-Dateien sucht sich GNU Make die entsprechenden Regeln aus seiner internen Regel-Datenbank. Für .f03-Dateien wurde der entsprechende Befehl hier von uns explizit durch eine "Pattern Rule" vorgegeben.

Die make-Ausgabe sieht so aus:

gfortran -c main.f03
cc    -c -o func.o func.c
gfortran   -c -o sub.o sub.f
gfortran -o prog main.o func.o sub.o

Solange die Quelldateien im selben Verzeichnis liegen, ist die Erstellung eines Makefiles ziemlich einfach. Wenn aber die Quelldateien gestaffelt in Unterverzeichnissen gespeichert sind und womöglich noch Abhängigkeiten von einem Unterverzeichis zum anderen gegeben sind, dann kann die ganze Sache ziemlich kompliziert werden. Im Anschluss wird eine einfache nichtrekursive Make-Variante gezeigt.

Nichtrekursive Make-Variante

Bearbeiten

Vor der Programmerstellung:

-- (D) projektverzeichnis
 |-- (F) Makefile
 |-- (F) module.mk
 |-- (F) main.f90
 |
 |-- (D) kreis
 | |-- (F) module.mk
 | |-- (F) kreis.f90
 | |-- (F) kreissegment.f90
 |
 |-- (D) quadrat
 | |-- (F) module.mk
 | |-- (F) quadrat.f90 

(D) ... directory
(F) ... file

Nach der Programmerstellung durch Aufruf von make:

-- (D) projektverzeichnis
 |-- (F) Makefile
 |-- (F) module.mk
 |-- (F) main.f90
 |-- (F) main.o
 |-- (F) prog
 |-- (F) kreis.mod
 |-- (F) kreissegment.mod
 |-- (F) quadrat.mod
 |
 |-- (D) kreis
 | |-- (F) module.mk
 | |-- (F) kreis.f90
 | |-- (F) kreissegment.f90
 | |-- (F) kreis.o
 | |-- (F) kreissegment.o
 |
 |-- (D) quadrat
 | |-- (F) module.mk
 | |-- (F) quadrat.f90 
 | |-- (F) quadrat.o

Quellcode-Dateien

Bearbeiten

main.f90:

Fortran 90/95-Code (free source form)
program main
  use kreis
  use kreissegment
  use quadrat
  implicit none
  
  call k()
  call q()
  call ks()
end program main 

kreis/kreis.f90:

Fortran 90/95-Code (free source form)
module kreis
  implicit none
 
  private
  public :: k
    
  contains
    subroutine k()
      print *, "Ich bin ein Kreis!"
    end subroutine k
end module kreis

kreis/kreissegment.f90:

Fortran 90/95-Code (free source form)
module kreissegment
  use kreis
  implicit none
  
  private
  public :: ks
  
  contains
    subroutine ks()
      call k()
      print *, "Hihi, war nur ein Scherz. Ich bin ein Kreissegment!"
    end subroutine ks
end module kreissegment

quadrat/quadrat.f90:

Fortran 90/95-Code (free source form)
module quadrat
  implicit none

  private
  public :: q
  
  contains
    subroutine q()
      print *, "Ich bin ein Quadrat!"
    end subroutine q
end module quadrat

Makefile, Include-Dateien

Bearbeiten

Makefile:

FC       := g95
SRC      := 

OBJ      = $(subst .f90,.o,$(SRC))

%.o: %.f90
	$(FC) -c -o $@ $<

include kreis/module.mk
include quadrat/module.mk
include module.mk

prog: $(OBJ)
	$(FC) -o $@ $^

module.mk:

SRC += main.f90

kreis/module.mk:

SRC += kreis/kreis.f90 kreis/kreissegment.f90

quadrat/module.mk:

SRC += quadrat/quadrat.f90

Es gibt nur ein Makefile im Projekthauptverzeichnis. Sämtliche unterverzeichnisspezifischen Details (hier nur die Bekanntgabe der Quellcodedateien) werden in den jeweiligen Unterverzeichnissen in eigenen Include-Dateien (.mk) festgelegt und in das Makefile eingebunden. Da, anders als beim rekursiven Make, nicht in die einzelnen Unterverzeichnisse gewechselt wird, werden allfällige mod-Dateien auch nur in das Projekthauptverzeichnis (= das aktuelle Verzeichnis) geschrieben.

Weiterführende Make-Infos

Bearbeiten

CMake ist kein Make-Klon, sondern ein moderner Autotools-Ersatz.

Gleiches Beispiel wie bei [1], es muss in diesem Fall nur eine CMakeLists.txt-Datei im Projekthauptverzeichnis erstellt werden. Makefile und dazugehörende Dateien werden automatisch beim cmake-Aufruf erstellt.

CMakeLists.txt:

PROJECT(bsp Fortran)

SET(src
      main.f90
      kreis/kreis.f90
      kreis/kreissegment.f90
      quadrat/quadrat.f90
   )

ADD_EXECUTABLE(prog ${src})

Generieren der Makefiles, etc.:

  • FC=g95 cmake .
-- Check for working Fortran compiler: /xyz/bin/g95
-- Check for working Fortran compiler: /xyz/bin/g95 -- works
-- Checking whether /xyz/bin/g95 supports Fortran 90
-- Checking whether /xyz/bin/g95 supports Fortran 90 -- yes
-- Configuring done
-- Generating done
-- Build files have been written to: /abc/projektverzeichnis

Mittels FC=... wird der zu verwendende Fortran-Compiler festgelegt. Wenn irgendein auf dem System installierter Fortran-Compiler verwendet werden soll, kann diese Vorgabe auch entfallen. In der CMakeLists.txt muss die Programmiersprache Fortran ausdrücklich aktiviert werden. Entweder wie hier im PROJECT-Statement oder alternativ auch über die ENABLE_LANGUAGE-Anweisung.


Programmerstellung:

  • make
Scanning dependencies of target prog
[ 25%] Building Fortran object CMakeFiles/prog.dir/kreis/kreis.o
[ 50%] Building Fortran object CMakeFiles/prog.dir/kreis/kreissegment.o
[ 75%] Building Fortran object CMakeFiles/prog.dir/quadrat/quadrat.o
[100%] Building Fortran object CMakeFiles/prog.dir/main.o
Linking Fortran executable prog

CMake (2.4-patch 7) erkennt nur Dateien mit den Endungen f, F, ,f77, F77, f90, F90, for, f95 und F95, jedoch keine mit f03 oder F03.


CMake-Homepage:


<< zur Fortran-Startseite
< Anhang D: Quellcodedokumentation Anhang F: Photran >