CMake Fortran Issues: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
No edit summary
(Replace content with link to new CMake community wiki)
 
(57 intermediate revisions by 4 users not shown)
Line 1: Line 1:
__TOC__
{{CMake/Template/Moved}}


= Introduction =
This page has moved [https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/languages/fortran/Fortran-Issues here].
CMake has a number of Fortran issues that have been discussed many different times on list and duplicated a fair number of times in the bug tracker as well.
 
Maik Beckmann is trying to make sense of all the confusion by collecting information on all Fortran issues at http://www.cmake.org/Bug/view.php?id=5809
 
Please join the work there by
 
* Contributing patches.
* Testing the patches that already exist there.
* Reporting things that don't work.
* Sending simplified examples of things which don't work.
* Sharing your expert knowledge of CMake.
 
= Concepts expressed using Makefiles =
 
This section is intended to discuss the makefile rules which CMake has to
generate.
 
== A simple program ==
 
A f9x program which is build by compiling in linking two source files ''a.f90'' and ''main.f90''.
The tree structure is:
* example_simpleProgram
** build
***  Makefile
*** prog.dir
**** build.make
** main.f90
** a.f90
 
a.f90:
<pre>
SUBROUTINE printHello
    WRITE(*,*) "Hello f9x world"
END SUBROUTINE
</pre>
 
main.f90:
<pre>
PROGRAM hello
    CALL printHello
END PROGRAM
</pre>
 
Makefile:
<pre>
all: prog.dir/all
 
prog.dir/all:
$(MAKE) -f prog.dir/build.make prog.dir/all
 
clean:
$(MAKE) -f prog.dir/build.make prog.dir/clean
</pre>
 
build.make:
<pre>
prog.dir/all: prog.dir/prog
 
prog.dir/prog:  prog.dir/a.o prog.dir/main.o
gfortran -o prog.dir/prog  prog.dir/a.o prog.dir/main.o
prog.dir/a.o: ../a.f90
gfortran -o prog.dir/a.o  -c ../a.f90
prog.dir/main.o: ../main.f90
gfortran -o prog.dir/main.o  -c ../main.f90
prog.dir/clean:
rm prog.dir/a.o prog.dir/main.o prog.dir/prog
</pre>
 
Now change into ''build'' and type
: $ make
to build. The current CMake is able to build the same without any problems. This is also valid for any fortran code that doesn't use modules.
 
You can download this example as tarball example_simpleProgram.tar.gz at http://www.cmake.org/Bug/view.php?id=5809
 
== A simple program with module ==
 
The same as before, but now ''a.f90'' provides a module which ''main.f90'' uses.
The tree structure is:
* example_simpleProgram_withModule
** build
***  Makefile
*** prog.dir
**** build.make
** main.f90
** a.f90
 
a.f90:
<pre>
MODULE localMod
!
CONTAINS
    SUBROUTINE printHello
        WRITE(*,*) "Hello f9x world"
    END SUBROUTINE
END MODULE
</pre>
 
main.f90:
<pre>
PROGRAM hello
    USE localMod
    CALL printHello
END PROGRAM
</pre>
 
Makefile:
<pre>
all: prog.dir/all
 
prog.dir/all:
$(MAKE) -f prog.dir/build.make prog.dir/all
 
clean:
$(MAKE) -f prog.dir/build.make prog.dir/clean
</pre>
 
build.make:
<pre>
prog.dir/all: prog.dir/prog
 
 
prog.dir/prog:  prog.dir/a.o prog.dir/main.o
gfortran -o prog.dir/prog  prog.dir/a.o prog.dir/main.o
 
prog.dir/a.o: ../a.f90
gfortran -o prog.dir/a.o  -c ../a.f90 -M prog.dir
prog.dir/localmod.mod: prog.dir/a.o
prog.dir/main.o: ../main.f90 prog.dir/localmod.mod
gfortran -o prog.dir/main.o  -c ../main.f90 -I prog.dir
prog.dir/clean:
rm prog.dir/localmod.mod prog.dir/a.o prog.dir/main.o prog.dir/prog
</pre>
 
Now change into ''build'' and type
: $ make
to build.  This is nothing the current CMake can't do.  Now
do (you're at the build directory)
  $ touch ../a.f90
and enter
  $ make
again.  You'll see that a.f90 is recompiled, like the current CMake does,
but main.f90  is recompiled too!  This is different from current CMake, but its
the right way, since a module dependency is a compile time dependency like an
include.
 
== Executable depending on external lib ==
 
This example build a executable target which
# provides a module
# uses the provided module
# uses a module of a external library
 
structure:
* example_dependingOn_externalLib
** extLib
*** include
**** externalmod.mod
*** lib
**** libmylib.a
** myproject
*** build
**** Makefile
**** prog.dir
***** build.make
*** a.f90
*** main.f90
 
 
You can download this example as tarball example_dependingOn_externalLib.tar.gz
at http://www.cmake.org/Bug/view.php?id=5809 . The extlib folder contains the source and a Makefile to build and install the lib by typing
: $ make install
 
Now the contents of myproject
 
a.f90:
<pre>
MODULE localMod
!
CONTAINS
    SUBROUTINE printLocalModGreeting
        WRITE(*,*) "Greetings from Module localMod"
    END SUBROUTINE
END MODULE
</pre>
 
main.f90:
<pre>
PROGRAM hello
    USE localMod
    USE externalMod
    CALL printLocalModGreeting
    CALL printExtModGreeting
END PROGRAM
</pre>
 
Makefile:
<pre>
all: prog.dir/all
 
prog.dir/all:
$(MAKE) -f prog.dir/build.make prog.dir/all
 
clean:
$(MAKE) -f prog.dir/build.make prog.dir/clean
</pre>
 
build.make:
<pre>
prog.dir/all: prog.dir/prog
 
 
prog.dir/prog:  prog.dir/a.o prog.dir/main.o
gfortran -o prog.dir/prog  prog.dir/a.o prog.dir/main.o ../../extLib/lib/libmylib.a
 
prog.dir/a.o: ../a.f90
gfortran -o prog.dir/a.o  -c ../a.f90 -M prog.dir
prog.dir/localmod.mod: prog.dir/a.o
prog.dir/main.o: ../main.f90 prog.dir/localmod.mod
gfortran -o prog.dir/main.o -c ../main.f90 -I prog.dir -I ../../extLib/include
prog.dir/clean:
rm prog.dir/localmod.mod prog.dir/a.o prog.dir/main.o prog.dir/prog
</pre>
 
== Executable target depending on lib target ==
 
structure:
* example_depending_libTarget
** build
*** Makefile
*** lib.dir
**** build.make
**** libmodx.mod.stamp
**** libmody.mod.stamp
*** prog.dir
**** build.make
** lib
*** a.f90
*** b.f90
** prog
*** a.f90
*** main.f90
 
contents...
 
lib/a.f90:
<pre>
MODULE libModX
    USE libModY
END MODULE
</pre>
 
lib/b.f90:
<pre>
MODULE libModY
END MODULE
</pre>
 
prog/a.f90:
<pre>
MODULE localMod
END MODULE
</pre>
 
prog/main.f90:
<pre>
PROGRAM hello
    USE localMod
    USE libModX
 
    WRITE(*,*) 'Hello, F90 world.'
END PROGRAM
</pre>
 
build/Makefile:
<pre>
all: lib.dir/all prog.dir/all
 
lib.dir/all:
$(MAKE) -f lib.dir/build.make
 
prog.dir/all: lib.dir/all
$(MAKE) -f prog.dir/build.make
</pre>
 
build/lib.dir/build.make:
<pre>
lib.dir/all: lib.dir/mylib
 
lib.dir/mylib: lib.dir/libmylib.a
 
lib.dir/libmylib.a: lib.dir/a.o lib.dir/b.o
ar rc lib.dir/libmylib.a lib.dir/a.o lib.dir/b.o 
ranlib lib.dir/libmylib.a
 
lib.dir/a.o: ../lib/a.f90 lib.dir/libmody.mod
gfortran -o lib.dir/a.o -c ../lib/a.f90 -M lib.dir
touch lib.dir/libmodx.mod.stamp
lib.dir/b.o: ../lib/b.f90
gfortran -o lib.dir/b.o -c ../lib/b.f90  -M lib.dir
touch lib.dir/libmody.mod.stamp
 
lib.dir/libmodx.mod: lib.dir/a.o
lib.dir/libmody.mod: lib.dir/b.o
 
 
lib.dir/clean:
rm lib.dir/a.o lib.dir/b.o lib.dir/libmylib.a
rm lib.dir/libmodx.mod lib.dir/libmody.mod
</pre>
 
build/prog.dir/build.make
<pre>
prog.dir/all: prog.dir/prog
 
 
prog.dir/prog: prog.dir/main.o prog.dir/a.o
gfortran -o prog.dir/prog  prog.dir/main.o prog.dir/a.o  lib.dir/libmylib.a
 
prog.dir/a.o: ../prog/a.f90
gfortran -o prog.dir/a.o -c ../prog/a.f90 -M prog.dir
prog.dir/localmod.mod: prog.dir/a.o
 
prog.dir/main.o: lib.dir/libmodx.mod.stamp
prog.dir/main.o: ../prog/main.f90 prog.dir/localmod.mod
gfortran -o prog.dir/main.o -c ../prog/main.f90 -I lib.dir -I prog.dir
 
 
 
prog.dir/clean:
rm prog.dir/a.o prog.dir/main.o prog.dir/prog prog.dir/localmod.mod
</pre>
 
== Finally: Executable target depending on lib target and external lib ==
 
structure:
* example_final
** extLib
*** include
**** externalmod.mod
*** lib
**** libmyextlib.a
** myproject
*** build
**** Makefile
**** lib.dir
***** build.make
***** libmodx.mod.stamp
***** libmody.mod.stamp
**** prog.dir
***** build.make
*** lib
**** a.f90
**** b.f90
*** prog
**** a.f90
**** main.f90
 
 
 
You can download this example as tarball example_final.tar.gz
at http://www.cmake.org/Bug/view.php?id=5809 . The extlib folder contains the source and a Makefile to build and install the lib by typing
: $ make install
 
Content...
 
lib/a.f90:
<pre>
MODULE libModX
    USE libModY
END MODULE
</pre>
 
lib/b.f90:
<pre>
MODULE libModY
END MODULE
</pre>
 
prog/a.f90:
<pre>
MODULE localMod
END MODULE
</pre>
 
 
prog/b.f90:
<pre>
PROGRAM hello
    USE localMod
    USE libModX
    USE externalMod
 
    WRITE(*,*) 'Hello, F90 world.'
    CALL printExtModGreeting
END PROGRAM
</pre>
 
 
build/Makefile:
<pre>
all: lib.dir/all prog.dir/all
 
lib.dir/all:
$(MAKE) -f lib.dir/build.make
 
prog.dir/all: lib.dir/all
$(MAKE) -f prog.dir/build.make
</pre>
 
build/lib.dir/build.make:
<pre>
lib.dir/all: lib.dir/mylib
 
lib.dir/mylib: lib.dir/libmylib.a
 
lib.dir/libmylib.a: lib.dir/a.o lib.dir/b.o
ar rc lib.dir/libmylib.a lib.dir/a.o lib.dir/b.o 
ranlib lib.dir/libmylib.a
 
lib.dir/a.o: ../lib/a.f90 lib.dir/libmody.mod
gfortran -o lib.dir/a.o -c ../lib/a.f90 -M lib.dir
touch lib.dir/libmodx.mod.stamp
lib.dir/b.o: ../lib/b.f90
gfortran -o lib.dir/b.o -c ../lib/b.f90  -M lib.dir
touch lib.dir/libmody.mod.stamp
 
lib.dir/libmodx.mod: lib.dir/a.o
lib.dir/libmody.mod: lib.dir/b.o
 
 
lib.dir/clean:
rm lib.dir/a.o lib.dir/b.o lib.dir/libmylib.a
rm lib.dir/libmodx.mod lib.dir/libmody.mod
</pre>
 
build/prog.dir/build.make:
<pre>
prog.dir/all: prog.dir/prog
 
prog.dir/prog: ../../extLib/lib/libmyextlib.a
prog.dir/prog: prog.dir/main.o prog.dir/a.o ../../extLib/lib/libmyextlib.a
gfortran -o prog.dir/prog  prog.dir/main.o prog.dir/a.o  lib.dir/libmylib.a ../../extLib/lib/libmyextlib.a
 
prog.dir/a.o: ../prog/a.f90
gfortran -o prog.dir/a.o -c ../prog/a.f90 -M prog.dir
prog.dir/localmod.mod: prog.dir/a.o
 
prog.dir/main.o: lib.dir/libmodx.mod.stamp
prog.dir/main.o: ../../extLib/include/externalmod.mod
prog.dir/main.o: ../prog/main.f90 prog.dir/localmod.mod
gfortran -o prog.dir/main.o -c ../prog/main.f90 -I lib.dir -I prog.dir -I ../../extLib/include
 
 
 
prog.dir/clean:
rm prog.dir/a.o prog.dir/main.o prog.dir/prog prog.dir/localmod.mod
</pre>

Latest revision as of 15:41, 30 April 2018


The CMake community Wiki has moved to the Kitware GitLab Instance.

This page has moved here.