wiki:make:compile
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| wiki:make:compile [2014/08/18 10:05] – Add ''.mod'' jensv | wiki:make:compile [2022/07/21 06:59] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ===Compiling Code=== | ||
| + | |||
| + | To compile code we use a compiler. Popular choices for Fortran and C are either gcc or intel compilers. In this example we will look at compiling Fortran with gfortran. gfortran is an open source GNU compiler. It is actually more than just a compiler. When we call gfortran we are calling a compiler driver which decides what tasks to send to a fortran compiler, assembler and linker. Often we have a source code that consists of many different files. Subroutines in each file are called by code in the other files. These files need to be linked together. | ||
| + | |||
| + | There are two steps in building programs: | ||
| + | - Compiling the individual source files into object files | ||
| + | - Linking the files with each other and numerical libraries | ||
| + | |||
| + | In the first step, compiling, gfortran goes through the source code files and converts them to assembler, which are instructions to run on a CPU. This step usually produces object files ending in '' | ||
| + | |||
| + | To compile a source file we use the following command: | ||
| + | |||
| + | $ gfortran -c file1.f90 | ||
| + | |||
| + | The second step, linking, gfortran links together the compiled object files and, optionally, external numerical libraries into an executable file. **Blas** and **Lapack** are popular numerical libraries. They contain many fast subroutines for manipulating matrices. | ||
| + | |||
| + | To link files together we can use the following command: | ||
| + | |||
| + | $ gfortran -o file1.o file2.o file3.o -L/usr/lib/ -llpack -lblas | ||
| + | |||
| + | Here the option '' | ||
| + | |||
| + | But we have to compile the files in right order, as they depend on each other. This is where make can help us. | ||
| + | |||
| + | I made an example code for you called inverse. It inverts a simple 3x3 matrix using lapack. It is a simple code and it is not really important that we understand it. | ||
| + | It is more important to note that I divided the code up into four different '' | ||
| + | inverse.f90 is the main file which calls subroutines from input.f90 and invert.f90. invert.f90 calls a subroutine from lu_decompose.f90. | ||
| + | |||
| + | I also created a simple makefile to build the program let's take a look and see if we can understand it. | ||
| + | |||
| + | #This is a makefile for inverse. | ||
| + | | ||
| + | F90 = gfortran | ||
| + | | ||
| + | LIBDIR = -L/usr/lib | ||
| + | | ||
| + | LIBS = \ | ||
| + | $(LIBDIR) \ | ||
| + | -llapack \ | ||
| + | -lblas | ||
| + | | ||
| + | OBJS = \ | ||
| + | lu_decompose.o \ | ||
| + | invert.o \ | ||
| + | input.o \ | ||
| + | inverse.o \ | ||
| + | | ||
| + | | ||
| + | %.o:%.f90 | ||
| + | $(F90) -c $*.f90 | ||
| + | | ||
| + | inverse: $(OBJS) | ||
| + | $(F90) -o inverse $(OBJS) $(LIBS) | ||
| + | | ||
| + | # | ||
| + | | ||
| + | invert.o: invert.f90 lu_decompose | ||
| + | inverse.o: inverse.f90 input.o invert.o | ||
| + | input.o: input.f90 | ||
| + | lu_decompose.o: | ||
| + | | ||
| + | clean: | ||
| + | rm -f *.o *.mod | ||
| + | |||
| + | |||
| + | Let's unpack this makefile. First we define some macros. The compiler as '' | ||
| + | |||
| + | Then we use a pattern rule to compile all '' | ||
| + | The executable inverse depends on all objects and links the object files with each other and the external libraries. | ||
| + | |||
| + | Next we define all the dependencies. Notice that we can define them here and make will automatically figure out in which order to run the pattern rule '' | ||
| + | |||
| + | Finally we define a clean target. It is not an actual file. Sometimes we call these targets **phoney** targets. It has a command to delete all the '' | ||
| + | It won't normally run since make only runs the first command in a makefile and any rules which create dependencies for the first target. But, we can force it to run by typing: | ||
| + | |||
| + | $ make clean | ||
| + | |||
| + | |||
| + | in the shell. | ||
| + | |||
| + | ===Suffix rules & Implicit rules=== | ||
| + | | ||
| + | You will likely encounter one more type of rule, suffix rules. | ||
| + | |||
| + | These rules consist of file suffixes listed together. e.g. '' | ||
| + | |||
| + | .SUFFIXES: .f90 | ||
| + | |||
| + | Suffix rules are obsolete and pattern rules should be used instead. But for compatibility with a old make files they are kept. I much prefer to use pattern rules since they are more general and clearer. | ||
| + | |||
| + | Another thing you should be aware of is that make includes several built-in rules also called **implicit rules**. We can see all of the variables and rules of make if we type '' | ||