Compiling and linking fortran code with MakeFile using Intel compiler - makefile

I have a code that is about 8,000 lines and is contained in the same one big bigcode.f90 file. It compiles without problems from the command line with intel compiler with the options:
mpif90 bigcode.f90 -r8 -O2 -xHost -override-limits -o output.out
I want to split this large file into modules and link them using makefile. Below I am listing the makefile. (So here I have main.f90, and also 8 modules linked to it, such as modparams.o and other 7). So I just broke the bigcode.f90 into 9 files. The problem is that when I compile with the makefile, it complains about things like
subroutine ended with "end" statement instead of "end subroutine"
integer passed to reals
some name conflicts between variable names and subroutine names.
All these may well be bad style. However the original bigcode.f90 had all of these, and it did not prevent it from compiling at all. I want to first replicate the results between the bigcode.f90 and the split version - and then I will make other changes.
I also made a copy of this makefile without any OBJECTS to link (just the single bigcode.f90), and that also compiled without any complains. Could somebody help me understand why is there inconsistency about what the compiler complains when there is one file versus when there are several linked files?
# DEFAULT FLAGS
CFLAGS := -I$(CPATH) -I$(F90_MODULES_PATH)
F90 := mpif90
# ADD ALL LIBRARIES HERE (with -l$LIBRARY_NAME)
LDFLAGS := -llapack -v
# ADD ALL SOURCE FILES HERE (with .o extension)
OBJECTS := modparams.o
OBJECTS += modleeplex.o
OBJECTS += modutilsmain.o
OBJECTS += modecon.o
OBJECTS += modindirect.o
OBJECTS += modijutils.o
OBJECTS += modselectstata.o
OBJECTS += modfcn.o
# ADD ADDITIONAL COMPILER FLAGS HERE
CFLAGS += -fbounds-check
CFLAGS += -ffree-line-length-350
CFLAGS += -r8
CFLAGS += -O2
CFLAGS += -xHost
CFLAGS += -override-limits
# ADD ADDITIONAL MODULE FOLDERS HERE (with -I$PATH_TO_FOLDER)
F90_MODULES += -I.
all: main
main: main.f90 $(OBJECTS)
$(F90) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $< -o $#
%.o : %.f90
$(F90) -c $< $(CFLAGS) $(F90_MODULES) $(LDFLAGS) -o $#
clean:
rm -rf $(OBJECTS) *.mod
When I compile, I get the following, and then a long list of errors.
mpif90 -c modfcn.f90 -I/opt/intel/composer_xe_2013.5.192/mkl/include:/opt/intel/composer_xe_2013.5.192/tbb/include:/opt/intel/composer_xe_20 13.5.192/mkl/include:/opt/intel/composer_xe_2013.5.192/tbb/include -I -fbounds-check -ffree-line-length-350 -r8 -O2 -xHost -override-lim its -I. -llapack -v -o modfcn.o
ifort: command line warning #10006: ignoring unknown option '-ffree-line-length-350'
ifort: command line remark #10010: option '-pthread' is deprecated and will be removed in a future release. See '-help deprecated'
ifort version 13.1.3

Related

Can't use LAPACK in makefile

I have program (in fortran) where I'm using three custom modules, which make use of LAPACK. Until now I've compiled my program using the following shell script:
filestring="main"
gfortran -c mod_exp.f90 mod_genmat.f90 mod_print.f90 $filestring.f90
gfortran mod_exp.o mod_genmat.o mod_print.o $filestring.o -llapack -lblas
rm mod_exp.o mod_genmat.o mod_print.o $filestring.o exponentiate.mod genmat.mod printing.mod printing_subrtns.mod
mv a.out $filestring
Since I've been using more and more modules and different programs using them, I've decided to start using makefiles. Following a tutorial, I managed to write the following:
FC = gfortran
FFLAGS = -Wall -Wextra -llapack -lblas #-fopenmp
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ)
clean:
#rm -f *.o *.mod main
However, when executing make, it says that the LAPACK functions are not recognized. One such mistake is the following:
/usr/bin/ld: mod_exp.o: in function `__exponentiate_MOD_diagun':
mod_exp.f90:(.text+0x37f): undefined reference to `zgees_'
...
collect2: error: ld returned 1 exit status
One possible mistake I've seen is that I need to specify the location of the libraries. However, it would seem strange since I didn't need to do it before; also, I don't know how to find it.
Please show the link command that make invoked, that caused the error to be generated.
I'm confident that if you cut and paste that exact command line to your shell prompt, you will get the same error you see when make runs it. So the problem is not make, but your link command.
The problem is that you have put the libraries before the objects in the link line. Libraries should come at the end, after the objects, else when the linker examines the libraries it doesn't know what symbols will need to be included (because no objects have been parsed yet to see what symbols are missing).
This is why LDLIBS is traditionally a separate variable:
FC = gfortran
FFLAGS = -Wall -Wextra #-fopenmp
LDLIBS = -llapack -lblas
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ) $(LDLIBS)

Why aren't my variables expanding in my makefile?

I'm using mingw32-make to run my makefile. The contents of the Makefile are the following:
#OBJS specifies which files to compile as part of the project
OBJS = SDLpp.o SDLpp_exception.o SDLpp_window.o
#CC specifies which compiler we're using
CC = g++
#INCLUDE_PATHS specifies the additional include paths we'll need
INCLUDE_PATHS = -IC:\mingw_dev_lib\include\SDL2 \
-IC:\mingw_dev_lib\include\SDL_image \
-IC:\mingw_dev_lib\include\SDLpp
#LIBRARY_PATHS specifies the additional library paths we'll need
LIBRARY_PATHS = -LC:\mingw_dev_lib\lib
#COMPILER_FLAGS specifies the additional compilation options we're using
# -w suppresses all warnings
# -Wall includes all warnings
# -Wl,-subsystem,windows gets rid of the console window
COMPILER_FLAGS = -Wall
#LINKER_FLAGS specifies the libraries we're linking against
LINKER_FLAGS = -lmingw32 -lSDL2main -lSDL2 -lSDL2_image
#LIB_NAME specifies the name of our library
LIB_NAME = libSDLcpp.a
#This is the target that compiles our executable
all : $(OBJS)
ar rvs $(LIB_NAME) $(OBJS)
%.o : %.c
$(CC) $< $(INCLUDE_PATHS) $(LIBRARY_PATHS) $(COMPILER_FLAGS) -c $(LINKER_FLAGS) -o $#
^(the white-space before the commands are tabs)^
When run, the shell outputs
g++ -c -o SDLpp.o SDLpp.cpp
which indicates that the other variables are not being expanding in the first pattern rule. Oddly, only CC is expanding into g++. Why is this happening?
The issue is not one of non-expanding variables. Rather, the makefile is using the default rule instead of the one you provided.
The reason may be that your rule uses *.c, while you likely have *.cpp files, IIRC.

Compiling SDL project on Raspberry Pi

I am trying to build a project with make (gcc on Raspbian)
Here is the makefile (I removed some unnecessary parts):
objects = 3d.o Affichage.o [...]
cflags = -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
poly : %(objects)
gcc $(cflags) $(objects) -o poly
($objects) : types.h
[...]
When running Make, I got:
cc -c -o Affichage.o Affichage.c
fatal error: SDL.h: No such file or directory
#include <SDL.h>
I checked the folders, everything seems ok. SDL.h is indeed in /usr/local/include/SDL2. I tried to remove options one by one in cflags, no luck...
What am I missing?
Make told you exact command it tried to execute:
cc -c -o Affichage.o Affichage.c
This don't have -I path, which is the source of an error.
You have target for your resulting executable but not for object files. Make have builtin rule to compile object files from C sources, but it isn't aware of your cflags variable. So far your options are:
Define your own pattern rule
e.g:
%.o: %.c
gcc $(cflags) -c $< -o $#
However, your cflags contains -lSDL2, which is linking flag, which should be specified only on linking phase (so technically it isn't cflag). Move it to separate variable (usually LIBS, which may then be enfolded into make's semi-standard LDFLAGS).
Use variables that make is aware of
In that case, it is CFLAGS:
CC:=gcc
CFLAGS:=-I/usr/local/include/SDL2
LIBS:=-lSDL2
LDFLAGS:=-L/usr/local/lib $(LIBS)
objects:=3d.o Affichage.o
poly: $(objects)
$(CC) $^ -o $# $(LDFLAGS)
$(objects): types.h
The rest will be done by implicit rules.

Compile program using a Makefile with gcc instead of clang

I am writing a program to spell-check a given text. On my pc I used this Makefile to compile the program:
# compiler to use
CC = clang
# flags to pass compiler
CFLAGS = -ggdb3 -O0 Qunused-arguments -std=c99 -Wall -Werror
# name for executable
EXE = speller
# space-separated list of header files
HDRS = dictionary.h
# space-separated list of source files
SRCS = speller.c dictionary.c
# automatically generated list of object files
OBJS = $(SRCS:.c=.o)
# default target
$(EXE): $(OBJS) $(HDRS) Makefile
$(CC) $(CFLAGS) -o $# $(OBJS) $(LIBS)
# dependencies
$(OBJS): $(HDRS) Makefile
I would like to continue programming on my Raspberry Pi but I only have gcc installed. Is it possible to make this Makefile work for gcc? I tried to change the compiler with:
CC = gcc
but It doesn't work. I get the error message "unrecognised option -Qunused-arguments".
The problem is that the -Q option which Clang accepts isn't an option which GCC recognises.
GCC and Clang are completely separate compilers, and so one shouldn't really expect one of them to understand the other's options. In fact, Clang does make some efforts to be modestly compatible with GCC, in large part to make it possible to use it as a drop-in replacement for GCC. However that compatibility isn't, and probably shouldn't be, complete.
So your solution is simply to change the CFLAGS definition at the same time as you change the CC definition.

how can I compile header and its run file without main

I have two files without main
X.h
X.cpp
I want compile these in one makefile
My makefile is ;
CXX = g++
CXXFLAGS_W = -Werror -Wunused-variable -Wunused-value -Wunused-function \
-Wfloat-equal -Wall
CXXFLAGS_M = -ansi -pedantic-errors
CXXFLAGS = ${CXXFLAGS_M} ${CXFLAGS_W}
all: main
./main
When I use like make X , compiler gives some error "undefined reference to main ". Due to that reason, I want new makefile. X can be any name .
You would generally have something like:
X.o: X.cpp X.h
g++ -c -o X.o X.cpp # or $(CXX) $(CXXFLAGS) -c -o ...
with whatever other flags you needed. -c tells the compiler to just compile rather than compile and link, and you don't usually compile the header file directly, rather you #include it in the cpp file.
Here's a makefile which combines two separate source files into a single executable:
xy: x.o y.o
g++ -o xy x.o y.o
x.o: x.cpp x.hpp y.hpp
g++ -c -o x.o x.cpp
y.o: y.cpp y.hpp
g++ -c -o y.o y.cpp
The x.cpp file includes x.hpp and y.hpp while y.cpp only includes y.hpp. The final executable is xy.
The first rule builds the executable from the two object files. The second and third rules builds the two object files, which is what I think you're asking for in the question.

Resources