|
|
(48 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>
| |
| | |
| 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/myextlib
| |
| | |
| 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>
| |