|
|
(34 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. You can download them as tarball examples_using_Makefiles.tar.gz at http://www.cmake.org/Bug/view.php?id=5809. To build one change into the corresponding ''build'' folder and enter
| |
| : $ make
| |
| After this initial build check dependencies by touching source files of your choice and running the
| |
| : $ make
| |
| command again.
| |
| | |
| '''Note:''' For examples which show how an external library providing modules is handled, the external library which resides at folder ''extLib'' for each of these examples has to be built and installed by running the command
| |
| : $ make install && make clean
| |
| inside folder ''extLib''.
| |
| | |
| | |
| == 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
| |
| | |
| 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
| |
| | |
| | |
| | |
| 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/b.f90:
| |
| <pre>
| |
| PROGRAM hello
| |
| USE localMod
| |
| USE libModX
| |
| USE externalMod
| |
| | |
| WRITE(*,*) 'Hello, F90 world.'
| |
| CALL printExtModGreeting
| |
| 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/b.o.requires: libmody.mod.proxy
| |
| | |
| lib.dir/requires: lib.dir/b.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: ../../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/main.o:
| |
| prog.dir/main.o: ../prog/main.f90
| |
| gfortran -o prog.dir/main.o -c ../prog/main.f90 -I lib.dir -I prog.dir -I ../../extLib/include
| |
| | |
| | |
| localmod.mod.proxy: prog.dir/a.o
| |
| libmodx.mod.proxy: # dummy
| |
| externalmod.mod.proxy: # dummy
| |
| | |
| prog.dir/main.o.requires: localmod.mod.proxy libmodx.mod.proxy externalmod.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>
| |
| | |
| === 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
| |
| | |
|
| |
| 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 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>
| |
| | |
| == Conclusion ==
| |
| | |
| === What keeps CMake from doing it like could be done shown above? ===
| |
| | |
| For each target CMake parses the source files and writes the dependencies one by one. This is ok for includes. But doing it this way CMake cannot determine if a required module of source file ''a.f90'' is provided by a source file ''b.f90'' of the same target or not. This is IMHO the reason why the CMake developer droped a direct dependency of the source file to a required module. As shown in the ''' rules like they are generated by current CMak''' sections an extra step called ''required'' was introduced. This works out if one want just to build, but isn't enought for developer needs (because recompilation isn't done as expected).
| |
| | |
| === What kind of changes have to be done to make it happen? ===
| |
| | |
| # Before the actually dependency tracking starts, CMake has to parse all fortran sources and to create a corresponding file i.e. ''mymodule.mod.stamp'' for ''mymodule''. This can be done soucre by source. Now CMake is able to search the build tree for a module.
| |
| # Rather than doing it one by one, all sources of a target have to be parsed before starting to write dependencies. This way CMake knows if a required modules is provided by itself or not.
| |
| # In case a required module ''mymod'' isn't provided by the same target
| |
| ## search the build-tree for ''mymod.mod.stamp''
| |
| ## if not found search it at the include paths
| |
|
| |
| | |
| Module dependency tracking superseeds include dependency tracking but
| |
| : '''Note:''' IMHO the code responsible for C/C++/Java dependency generation shouldn't be touched, since speed is a imporant advantage of CMake for developers!
| |