I try to use the makefile to link up some modules to the main program.
I have a module called SimParam_mod.f90 which has:
MODULE simParam
integer, parameter:: yDim = 80
integer, parameter:: xDim = 80
integer, parameter:: iterper = 100
integer, parameter:: tMax = 2000
END MODULE simParam
After compiling it using the make option:
MODDIR =../module
CFLAGS=-I$(IDIR)
OBJDIR=obj
LIBDIR =../lib
LIBS=-lm
CF=gfortran
CFLAGS=-I.
OBJ = main.o D2Q9Const_mod.o SimParam_mod.o
%.o: %.f90
$(CF) -c -O3 -o $# $< -I$(MODDIR)
run: $(OBJ)
$(CF) -o $# $^ $(CFLAGS)
the values stored for iterper and tMax are not updated. I save it correctly and the modules compiled with gfortran -c don't see any problem and the create the .mod files.
I checked the .mod files and they store it with values which are not the ones specified in the module.f90, iterper = 1 and tMax = 20 and should be 100 and 2000 respectively. All what I can say is that I don't know really how to use the make instructions and that these wrong values that get stored are former values that I had defined much earlier.. there is something that I miss..
Thanks in advance for your help!
Puigar
I just had to add as Mark said a command in the makefile to delete the .o and .mod files and to recompile the program. In that case works perfectly.
just adding:
rm -f *.o
Thanks to all the guys that were interested in the thread!
Puigar
Related
I am kinda rookie in makefile field but trying to write makefile that would go in two modes: normal mode make outputing executable file called say bingo depending on some files and a mode make debug outputing executable file called bingo.debug that shall be compiled with debug option. I'm trying to use target variable with the following result:
PROGRAM = bingo
SUFIX = .debug
CC = gcc
CFLAGS = -Wall -O2
DEBUG = -g -D DEBUG
all: $(PROGRAM)
debug: CFLAGS += $(DEBUG)
debug: PROGRAM += $(SUFIX)
debug: all
file1.o: file1.c file1.h
$(CC) -c $(CFLAGS) -o $# $<
file2.o: file2.c file2.h
$(CC) -c $(CFLAGS) -o $# $<
$(PROGRAM).o: $(PROGRAM).c
$(CC) -c $(CFLAGS) -o $# $<
$(PROGRAM): file1.o file2.o ($PROGRAM).o
$(CC) -o $# $^
.PHONY: all clean
clean:
rm -rf $(PROGRAM) *.o
It looks like make debug correctly compiles the file with debug flags but it does not change the file name (i.e. both modes outputs the same bingo file). Any help much appriciated!
You cannot use target-specific variables in targets. The documentation is very clear that they are available only in recipes.
In general it's problematic to do things this way, because make has no idea which objects were built with debug and which weren't. If you forget to do a complete clean and/or run make the wrong way then you'll get a mix of different object files: some compiled with debug and some not.
Instead, you should put your debug object files in a different directory from your non-debug object files so you don't have to worry about that.
The challenge is to create a makefile which takes a list of modules and does not require me to sort out precendence. For example, the modules are
mod allocations.f08 mod precision definitions.f08 mod unit values.f08
mod blocks.f08 mod shared.f08 mod parameters.f08
mod timers.f08
The main program is characterize.f08. The error message is
Fatal Error: Can't open module file ‘mprecisiondefinitions.mod’ for reading at (1): No such file or directory
The first statement in the main program is use mPrecisionDefinitions, the module defined in mod precision definitions.f08.
The following makefile, based upon Creating a FORTRAN makefile, is:
# compiler
FC := /usr/local/bin/gfortran
# compile flags
FCFLAGS = -g -c -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5
# link flags
FLFLAGS =
# source files and objects
SRCS = $(patsubst %.f08, %.o, $(wildcard *.f08))
# program name
PROGRAM = a.out
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FLFLAGS) -o $# $^
%.mod: %.f08
$(FC) $(FCFLAGS) -o $# $<
%.o: %.f08
$(FC) $(FCFLAGS) -o $# $<
clean:
rm -f *.o *.mod
For starters, I recommend to replace all spaces in your file names with underscores or something similar.
Spaces are almost universally used as separators, and any program that is started with something like
gfortran -c -o mod precision definitions.o mod precision definitions.f08
would interpret this line as 'create an object file called mod from the source files precision, definitions.o, mod, precision, and definitions.f08. And while there are ways to do it, with increasing automation, you have to jump more and more hoops.
In contrast, this works well:
gfortran -c -o mod_precision_definitions.o mod_precision_definitions.f08
I would use this command to change all the spaces into underscores:
rename 's/ /_/g' *.f08
If that doesn't work, use this command:
for f in *.f08; do mv "$f" ${f// /_}; done
Next, I wouldn't worry about .mod files. They get generated together with the object files when you compile a module. So while technically some routine that uses a module requires the .mod file for that module, you might as well claim in your Makefile that it depends on the object file itself.
So with that said, here's the Makefile I would use (with some assumed inter-module dependencies added):
# Find all source files, create a list of corresponding object files
SRCS=$(wildcard *.f08)
OBJS=$(patsubst %.f08,%.o,$(SRCS))
# Ditto for mods (They will be in both lists)
MODS=$(wildcard mod*.f08)
MOD_OBJS=$(patsubst %.f08,%.o,$(MODS))
# Compiler/Linker settings
FC = gfortran
FLFLAGS = -g
FCFLAGS = -g -c -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5
PROGRAM = characterize
PRG_OBJ = $(PROGRAM).o
# make without parameters will make first target found.
default : $(PROGRAM)
# Compiler steps for all objects
$(OBJS) : %.o : %.f08
$(FC) $(FCFLAGS) -o $# $<
# Linker
$(PROGRAM) : $(OBJS)
$(FC) $(FLFLAGS) -o $# $^
# If something doesn't work right, have a 'make debug' to
# show what each variable contains.
debug:
#echo "SRCS = $(SRCS)"
#echo "OBJS = $(OBJS)"
#echo "MODS = $(MODS)"
#echo "MOD_OBJS = $(MOD_OBJS)"
#echo "PROGRAM = $(PROGRAM)"
#echo "PRG_OBJ = $(PRG_OBJ)"
clean:
rm -rf $(OBJS) $(PROGRAM) $(patsubst %.o,%.mod,$(MOD_OBJS))
.PHONY: debug default clean
# Dependencies
# Main program depends on all modules
$(PRG_OBJ) : $(MOD_OBJS)
# Blocks and allocations depends on shared
mod_blocks.o mod_allocations.o : mod_shared.o
I am trying to build a very simple Makefile, that intends to use a homemade library (libf904QC.a) made of Fortran modules. The library is in /usr/local/lib64 whereas the corresponding .mod files are in /usr/local/include/f904QC
Here is the Makefile
# Makefile
NAME=NPManip
FFLAGS= -ffpe-trap=overflow -c -O3
LFLAGS=
PATH2LIB=/usr/local/lib64/
INCLUDEDIR=/usr/local/include/f904QC/
#
LIB=-L$(PATH2LIB) -I$(INCLUDEDIR) -lf904QC.a
OBJS = \
tools_NPManip.o\
NPManip.o
%.o: %.f90
gfortran $(LIB) $(FFLAGS) $*.f90
NPM: $(OBJS)
gfortran $(LFLAGS) $(OBJS) $(LIB) -o $(NAME)
clean:
#if test -e $$HOME/bin/$(NAME); then \
rm $$HOME/bin/$(NAME); \
fi
rm *.o *.mod
mrproper: clean
rm $(NAME)
install:
ln -s $(shell pwd)/$(NAME) $$HOME/bin/.
I get the following error message :
gfortran tools_NPManip.o NPManip.o -L/usr/local/lib64/ -I/usr/local/include/f904QC/ -lf904QC.a -o NPManip
/usr/lib64/gcc/x86_64-suse-linux/4.7/../../../../x86_64-suse-linux/bin/ld: cannot find -lf904QC.a
collect2: error: ld returned 1 exit status
make: * [NPM] Erreur 1
Where is the mistake? It is not obvious to me since libf904QC.o is actually located in /usr/local/lib64, which is defined by the -L option.
Thnak you for your help
You should specify either the full path to the library /usr/local/lib64/libf904QC.a or alternatively -L/usr/local/lib64 -lf90QC, without the .a in that case. From man ld:
-l namespec
--library=namespec
Add the archive or object file specified by namespec to the list of files to link. This option may be used any number of
times. If namespec is of the form :filename, ld will search the library path for a file called filename, otherwise it
will search the library path for a file called libnamespec.a.
-L searchdir
--library-path=searchdir
Add path searchdir to the list of paths that ld will search for archive libraries and ld control scripts. You may use
this option any number of times. The directories are searched in the order in which they are specified on the command
line. Directories specified on the command line are searched before the default directories. All -L options apply to
all -l options, regardless of the order in which the options appear. -L options do not affect how ld searches for a
linker script unless -T option is specified.
I am new to Fortran. I am working on a research project where I am using an open source project that has several files distributed in multiple folders. i found the dependency of each programs but could not figure out how to compile them.
I have source code distributed in three folders.
a)modules
b)interfaces
c)subroutines
I would like to run a program named as 'Main.f90' in subroutines folder, this program has dependency of source codes from modules and interfaces folders.
I am using eclipse for folder structure and makefile to compile.
Any help with this is appreciated.
UPDATE:
I followed the answer posted by #MBR and #Stefan, for some reason VPATH did not able to find programs in source code so I explicitly gave path to those source folder in my Makefile. below is my make file script.
.PHONY: Mopac_exe clean
# Change this line if you are using a different Fortran compiler
FORTRAN_COMPILER = gfortran
SRC = src
#make main program
Mopac_exe: subroutines mopac.o
$(FORTRAN_COMPILER) mopac.o *.o -O2 -g -o bin/Mopac_exe -I Modules/
#compile all the subroutines
subroutines: interfaces
$(FORTRAN_COMPILER) -c $(SRC)/subroutines/*.F90 -J Modules/Subroutines/ -I Modules/
#compiles all the interfaces
interfaces: modules
$(FORTRAN_COMPILER) -c $(SRC)/interfaces/*.f90 -J Modules/
# build all the modules and generate .mod file in Modules directory
modules: build_vast_kind
$(FORTRAN_COMPILER) -c $(SRC)/modules/*.f90 -J Modules/
$(FORTRAN_COMPILER) -c $(SRC)/modules/*.F90 -J Modules/
# compile vastkind.f90 files and generates the .mod file in Modules directory.Every other Modules and interfaces are dependent on this.
build_vast_kind:clean
$(FORTRAN_COMPILER) -c $(SRC)/modules/vastkind.f90 -J Modules/
clean:
rm -f bin/Mopac_exe *.mod
rm -f Modules/*.mod
rm -f *.o
I compiled all the modules and placed in Modules directory of root Folder.
All compilation goes well. I get error when I build the executable. I get following error.
gfortran mopac.o *.o -O2 -g -o bin/Mopac_exe -I Modules/
mopac.o: In function `main':
mopac.F90:(.text+0x27c1): multiple definition of `main'
mopac.o:mopac.F90:(.text+0x27c1): first defined here
getdat.o: In function `getdat_':
getdat.F90:(.text+0x22): undefined reference to `iargc_'
getdat.F90:(.text+0xf2): undefined reference to `getarg_'
symr.o: In function `symr_':
symr.F90:(.text+0xd3f): undefined reference to `symp_'
writmo.o: In function `writmo_':
writmo.F90:(.text+0x20c2): undefined reference to `volume_'
collect2: error: ld returned 1 exit status
make: *** [Mopac_exe] Error 1
`iargc_' is being used in 'getdat file and iargc is already compiled. why there is error while making the executable saying undefined reference? what am I missing?
You can do a Makefile which looks like that
F90=gfortran
FFLAGS = -O0
VPATH = modules:interfaces:subroutines:
MODOBJ = module1.o module2.o ...
your_executable: $(MODOBJ) main.o
$(F90) main.o -o your_executable
%.o:%.f90
$(F90) $(FFLAGS) -c $^ -o $#
VPATH is the paths of the directories where your Makefile will look for source files, so if you compile your source in the root directory of modules/, interfaces/ and subroutines/, you just have to set up VPATH like that.
If you have many objects and you don't want to write everything by hand, you can retrieve them using the following trick
F90 = gfortran
FFLAGS = -O0
VPATH = modules:interfaces:subroutines
SRCOBJ = $(wildcard modules/*f90)
MODOBJ = $(SRCOBJ:.f90=.o)
your_executable: $(MODOBJ) main.o
$(F90) main.o -o your_executable
%.o:%.f90
$(F90) $(FFLAGS) -c $^ -o $#
The wildcard command in a Makefile allows you to use a joker *; then you just have to say that in the strings you will retrieve in $(SRCOBJ), you want to substitute .f90 by .o to get the filenames of your modules.
You can create your Makefiles as usual. The biggest problem should be the .mod files. The easiest solution to this problem is to create a separate folder, where these files are stored and searched for.
This can be achieved with the -J and the -module flags for gfortran and ifort, respectively.
I have written a (GNU make) Makefile designed to perform automatic dependency tracking in header includes. Everything works great except that upon typing make a second time, the entire code base rebuilds. Only typing make the third time and successive times gives the message that nothing is to be done.
SRCDIR := src
INCDIR := inc
ifeq ($(DEBUG),1)
OBJDIR := debug_obj
BINDIR := debug_bin
else
OBJDIR := obj
BINDIR := bin
endif
BINS := prog1 prog2 prog3 prog4
SRCS := $(wildcard $(SRCDIR)/*.cpp)
OBJS := $(patsubst $(SRCDIR)/%,$(OBJDIR)/%,$(SRCS:.cpp=.o))
DEPS := $(OBJS:.o=.d)
CC := g++
COMMON_FLAGS := -Wall -Wextra -Werror -std=c++11 -pedantic
ifeq ($(DEBUG),1)
CXX_FLAGS := $(COMMON_FLAGS) -Og -g
else
CXX_FLAGS := $(COMMON_FLAGS) -O3 -D NDEBUG
endif
all: $(addprefix $(BINDIR)/,$(BINS)) | $(BINDIR)
$(OBJDIR) $(BINDIR):
# mkdir -p $#;
$(BINDIR)/%: $(OBJDIR)/%.o | $(BINDIR)
$(CC) $(CPP_FLAGS) $< -o $#;
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $(OBJDIR)
$(CC) $(CPP_FLAGS) -MMD -MP -c $< -o $#;
-include $(DEPS)
.PHONY: all clean
clean:
- rm -f $(OBJS);
- rm -f $(DEPS);
- rm -f $(addprefix $(BINDIR)/,$(BINS));
- rmdir $(OBJDIR) $(BINDIR) 2> /dev/null || true
Clearly some dependency had changed, so I tried running make -n -d | grep 'newer' following the first invocation of make, which shows this:
Prerequisite obj/prog1.o' is newer than targetbin/prog1'.
Prerequisite obj/prog2.o' is newer than targetbin/prog2'.
Prerequisite obj/prog3.o' is newer than targetbin/prog3'.
Prerequisite obj/prog4.o' is newer than targetbin/prog4'.
And ls -la obj/*
Showed the existence of the dependency (*.d) files but not the object (*.o) files. I assume that this is related to how g++ -MMD -MP works, but despite the apparent absence of object files, binaries are present after the first make.
The answer to this question suggests that both are generated at the same time, and man g++ does not dispute this as far as I can tell.
I've read a couple other questions and answers related to automatic dependency tracking, but I don't see this issue arising. Why is this happening? Can you suggest a fix?
Update
A more careful look at the first invocation of make shows this unexpected (to me) line at the end:
rm obj/prog1.o obj/prog2.o obj/prog3.o obj/prog4.o
That answers one question but raises another.
Update
I also found this in the debugging output.
Considering target file `prog1'.
File `prog1' does not exist.
make: *** No rule to make target `prog1'. Stop.
No implicit rule found for `prog1'.
Finished prerequisites of target file `prog1'.
Must remake target `prog1'.
For which I note that prog1 is missing the bin/ prefix. Nothing explains why the first run removes the object files, but the second run leaves them, however. That seems to be at the heart of the issue.
make was treating the object files as intermediates and deleting them accordingly. Adding:
.SECONDARY: $(OBJS)
solved the problem. I do not know why it was doing this the first invocation but not the second invocation. Comments are welcome.
The reason that the .o files are not present is that they're considered intermediate files so make deletes them. However, that shouldn't cause any problems in your build, because as long as make can envision the intermediate file it will realize it doesn't need to be rebuilt if its prerequisites are older than its parents (in this case, as long as prog1 is newer than prog1.cpp for example).
I was not able to reproduce your experience with the second build rebuilding everything. More details will be needed. The output you showed is not interesting because that's just saying that make does NOT need to rebuild the .o file (it's newer than the prerequisite). You need to find the lines in the output that explain why make does need to rebuild the .o file. If you provide that info we may be able to help.
Just a couple of comments on your makefile: first, I don't think it's a good idea to force the mkdir rule to always succeed. If the mkdir fails you WANT your build to fail. Probably you did this so it would not be a problem if the directory already exists, but that's not needed because the mkdir -p invocation will never fail just because the directory exists (but it will fail if the directory can't be created for other reasons such as permissions). Also you can combine those into a single rule with multiple targets:
$(BINDIR) $(OBJDIR):
#mkdir -p $#
Next, you don't need the semicolons in your command lines and in fact, adding them will cause your builds to be slightly slower.
Finally, a small nit, but the correct order of options in the compile line is -c -o $# $<; the source file is not (this is a common misconception) an argument to the -c option. The -c option, like -E, -s, etc. tells the compiler what output to create; in the case of -c it means compile into an object file. Those options do not take arguments. The filename is a separate argument.