CMake Fortran Issues: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
(Replace content with link to new CMake community wiki)
 
(44 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.  All examples are fully working.  To build one change into the corresponding ''build'' folder and enter
: $ make
Simply building isn't the fancy part.  Now try to touch a sourcefile of your choise and check if the build order is right.
 
 
== 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>
 
The rules generated by the '''current CMake covers all dependencies''' which can occur as long as '''no modules''' are used.
 
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>
 
=== rules like they are generated by current CMake ===
 
Makefile:
<pre>
all: prog.dir/all
 
prog.dir/all:
$(MAKE) -f prog.dir/build.make prog.dir/requires
$(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
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
localmod.mod.proxy: prog.dir/a.o
 
prog.dir/main.o.requires: localmod.mod.proxy
prog.dir/requires: prog.dir/main.o.requires
</pre>
 
After you build prog using this set of Makefiles
do (you're at the build directory)
  $ touch ../a.f90
and enter
  $ make
You'll see that a.f90 is recompiled and prog.dir/prog  is linked again. But main.f90 has to recompiled too, since a module dependency is a compile time dependency like an include.
 
=== rules like they could be generated ===
 
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>
 
After you build prog using this set of Makefiles
do (you're at the build directory)
  $ touch ../a.f90
and enter
  $ make
You'll see that a.f90 is recompiled, like the current CMake does,
but main.f90  is recompiled too, as it should be.
 
== 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
**** libmyextlib.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>
 
=== rules like they are generated by current CMake ===
Makefile:
<pre>
all: prog.dir/all
 
prog.dir/all:
$(MAKE) -f prog.dir/build.make prog.dir/requires
$(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: ../../extLib/lib/libmyextlib.a
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/libmyextlib.a
 
prog.dir/a.o: ../a.f90
gfortran -o prog.dir/a.o  -c ../a.f90 -M prog.dir
prog.dir/main.o: ../main.f90
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
externalmod.mod.proxy: # dummy
 
localmod.mod.proxy: prog.dir/a.o
 
prog.dir/main.o.requires: localmod.mod.proxy externalmod.mod.proxy
prog.dir/requires: prog.dir/main.o.requires
</pre>
 
This rules got the same problem as the example above (simple Program with module) plus it doesn't recognizes
if the external modules got updated.
 
=== rules like they could be generated ===
 
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: ../../extLib/lib/libmyextlib.a
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/libmyextlib.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>
 
These rules build everything in proper order and consider the timestamp of externalmod.mod.
 
== 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>
 
===  rules like they are generated by current CMake ===
 
build/Makefile:
<pre>
all: lib.dir/all prog.dir/all
 
lib.dir/all:
$(MAKE) -f lib.dir/build.make lib.dir/requires
$(MAKE) -f lib.dir/build.make lib.dir/all
 
prog.dir/all: lib.dir/all
$(MAKE) -f prog.dir/build.make  prog.dir/requires
$(MAKE) -f prog.dir/build.make  prog.dir/all
 
clean:
$(MAKE) -f prog.dir/build.make prog.dir/clean
$(MAKE) -f lib.dir/build.make lib.dir/clean
</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
gfortran -o lib.dir/a.o -c ../lib/a.f90 -M lib.dir
 
lib.dir/b.o: ../lib/b.f90
gfortran -o lib.dir/b.o -c ../lib/b.f90  -M lib.dir
 
libmody.mod.proxy: lib.dir/b.o
 
lib.dir/a.o.requires: libmody.mod.proxy
lib.dir/requires:  lib.dir/a.o.requires 
 
 
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: ../prog/main.f90
gfortran -o prog.dir/main.o -c ../prog/main.f90 -I lib.dir -I prog.dir
 
 
localmod.mod.proxy: prog.dir/a.o
libmodx.mod.proxy: # dummy
 
prog.dir/main.o.requires: localmod.mod.proxy libmodx.mod.proxy
prog.dir/requires: prog.dir/main.o.requires
 
 
prog.dir/clean:
rm prog.dir/a.o prog.dir/main.o prog.dir/prog prog.dir/localmod.mod
</pre>
 
Again everything is build, but isn't updated proper.
 
=== rules like they could be generated ===
 
build/Makefile:
<pre>
all: lib.dir/all prog.dir/all
 
lib.dir/all:
$(MAKE) -f lib.dir/build.make lib.dir/all
 
prog.dir/all: lib.dir/all
$(MAKE) -f prog.dir/build.make prog.dir/all
</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.