How to write a makefile for Fortran with modules? - makefile

gg=mpif90
DEPS=matrix.mod
OBJ= main.o sub1.o
main.out: $(OBJ)
$(gg) -o $# $^
%.mod:%.90 %.o
$(gg) -c -o $# $^
%.o:%.f90 $(DEPS)
$(gg) -c -o $# $^
.PHONY: clean
clean:
-rm -f *.o *~
Look. The main program is main.f90.sub1.f90 will be called by main.f90. Both will use matrix.f90 which is a module. I know I can directly generate the executable program without compile then link. But I do not like that way.

The mod file is only a by-product of compiling %.o, you shouldn't use -o $# here, change it to
%.mod: %.90
$(gg) -c $^
This will work for most cases, but not all. That's because the name of mod file depends only on the module name, it has nothing to do with the source file name. So the safest way is to specify the dependency explictly.
matrix.mod: matrix.f90
$(gg) -c matrix.f90
Sometimes one f90 source file can contain two or more modules.
matrix33.mod matrix99.mod: matrix.f90
$(gg) -c matrix.f90

Related

Makefile with different source types doesn't notice make.depend

I want my Makefile to accept different source file types. It does, but it does not recompile when I alter an include file. Here's the Makefile:
C_SOURCES := $(wildcard *.c)
CPP_SOURCES := $(wildcard *.cpp)
CC_SOURCES := $(wildcard *.cc)
ALL_SOURCES := $(notdir $(C_SOURCES) $(CPP_SOURCES) $(CC_SOURCES))
C_OBJECTS := ${C_SOURCES:.c=.o}
CPP_OBJECTS := ${CPP_SOURCES:.cpp=.o}
CC_OBJECTS := ${CC_SOURCES:.cc=.o}
ALL_OBJECTS := $(notdir $(C_OBJECTS) $(CPP_OBJECTS) $(CC_OBJECTS))
#############################################################
all: a.out
a.out: $(ALL_OBJECTS)
g++ -o $# -g $^
%.o: %.cpp
g++ -c $# -g $^
%.o: %.cc
g++ -c $# -g $^
%.o: %.c
g++ -c $# -g $^
clean:
rm -f a.out
rm -f *.o
make.depend: $(ALL_SOURCES)
g++ -MM $^ > $#
-include make.depend
The lines starting with *.o: are a recent addition -- I wondered if it might help. No effect.
make.depend is doing its job: I checked it out, and its dependencies are correct. (For my MCVE I have one source file main.cpp which includes date.h.)
main.o: main.cpp date.h
The output of $(info $(ALL_OBJECTS)) is main.o.
So: how can I get it to recognize changes to includes?
It would be helpful, when asking questions, to show an example of running the commands and what is printed. Given the makefile you provide I'd be surprised of make actually ran any commands at all, other than generating the depend file.
That's because this:
C_OBJECTS := ${C_SOURCES: .c =.o}
is invalid syntax. Or more precisely, it doesn't do what you want to do. It replaces the literal string _____.c__ (where the _ are whitespace... SO won't let me just use spaces) at the end of each word in C_SOURCES with .o. Of course you don't have any of those, so basically your ALL_OBJECTS variable contains just your source files (since no changes are made by the substitution).
You can use:
$(info $(ALL_OBJECTS))
to see what happens here.
This needs to be written:
C_OBJECTS := ${C_SOURCES:.c=.o}
CPP_OBJECTS := ${CPP_SOURCES:.cpp=.o}
CC_OBJECTS := ${CC_SOURCES:.cc=.o}
Whitespace in makefiles is very tricky. You definitely have to be careful where you put it and you can't add it anywhere you like.
Also I have no idea why you're using notdir since all your files are in the current directory.
And technically it's incorrect to compile .c files with the g++ compiler front-end.
ETA also your pattern rules are incorrect: you're missing the -o option to the compiler; they should all be the equivalent of:
%.o: %.c
g++ -c -o $# -g $^
Better is to use the standard make variables, then you can customize the behavior without rewriting all the rules:
CFLAGS = -g
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $# $<
Update Just use the comprehensively enginerred automatic dependency file generation #MadScientist describes at http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/. This works with both GCC and clang (due to clang's explicit goal to be commandline compatible to GCC).
For completeness' sake, my original answer:
The generated dependency rules must depend on the sources determined by the dependeny rule generating rule. This requires the -MT parameter to gcc.
I have included this as an example in a slightly cleaned up version of your GNUmakefile:
#############################################################
ALL_CFLAGS = -g
ALL_CXXFLAGS = -g
#############################################################
.PHONY: all
all: all-local
#############################################################
bin_PROGRAMS += test-cxx
test_cxx_OBJECTS += main.o
test_cxx_OBJECTS += main-c.o
test-cxx: $(test_cxx_OBJECTS)
$(LINK.cc) $(ALL_CXXFLAGS) -o $# $^
ALL_OBJECTS += $(test_cxx_OBJECTS)
#############################################################
%.o: %.cpp
$(COMPILE.cpp) $(ALL_CXXFLAGS) -o $# -c $<
%.o: %.cc
$(COMPILE.cc) $(ALL_CXXFLAGS) -o $# -c $<
%.o: %.c
$(COMPILE.c) $(ALL_CFLAGS) -o $# -c $<
#############################################################
%.dep: %.cpp
$(COMPILE.cpp) -MM -MT "$*.o $# " $< > $#.tmp
mv -f $#.tmp $#
%.dep: %.cc
$(COMPILE.cc) -MM -MT "$*.o $# " $< > $#.tmp
mv -f $#.tmp $#
%.dep: %.c
$(COMPILE.c) -MM -MT "$*.o $# " $< > $#.tmp
mv -f $#.tmp $#
ALL_DEPS = $(ALL_OBJECTS:.o=.dep)
-include $(ALL_DEPS)
#############################################################
.PHONY: all-local
all-local: $(bin_PROGRAMS)
.PHONY: clean
clean:
rm -f $(bin_PROGRAMS)
rm -f *.dep
rm -f *.o
#############################################################
The *.dep generating rules will recursively examine all included source files, and list them all in the generated *.dep file.
Using a separate *.dep file for each object file means that if you change only one source file, only the *.dep files needing regeneration will actually be regenerated.
The *.dep generating rule creates a *.dep.tmp file first, and only moves that to *.dep if generating the *.dep.tmp file has been successful. So if for some reason generating the *.dep.tmp file fails (e.g. you might be including a non-existing header file), you will not have a newly generated (and thus considered up to date) empty *.dep file being included by make.

Makefile to auto compile, assemble and link many files in a directory

Sorry for repetition, but I could not find the solution.
Following is the sequence of the commands I want Makefile to accomplish.
gcc-elf-gcc -S -combine loadStoreByte.c string.c lib_uart.c bubble_uart.c -o bubble_uart.s
gcc-elf-as -o startup.o startup.s;
gcc-elf-as -o handler.o handler.s;
gcc-elf-as -o bubble_uart.o bubble_uart.s;
gcc-elf-ld -o bubble_uart -T browtb.x bubble_uart.o startup.o handler.o;
That is, I want to compile all C files into a single S file and then assemeble all s files into corresponding object files and the link all object files into one executable.
I tried the following makefile. The individual targets work fine, but could not run all the target at the same time using "make all".
Please guide how to fix it.
CC = brownie32-elf-gcc
AS = brownie32-elf-as
LK = brownie32-elf-ld
SFILE = $(wildcard *.s)
OFILE = $(patsubst %.s,%,$(SFILE))
CFILE = $(wildcard *.c)
OBJ = $(wildcard *.o)
APP = bubble_uart
all: compile assemble link
link: $(OBJ)
$(LK) -o $(APP) -T browtb.x $^
assemble: $(OFILE)
%: %.s compile
$(AS) -o $#.o $<
compile: $(CFILE)
$(CC) -S -combine $^ -o $(APP).s
clean:
rm -f $(OBJ) $(APP) $(APP).s *.o
Thanks
Your makefile is not written with "best practices" and because of that it was easy for you to make mistakes. I will re-write your makefile here, with best practices, which solves all your problems. Please study it with the aid of the GNU Make manual.
The biggest single problem is that you have "procedures/actions", such as "assemble" as make targets. This makes the makefile into a kind of "procedural" program. GNU Make is not designed to be a procedural language, instead, it is a declarative language. The "targets" should not be actions, but actual files, or "phony" files, which should be collections of actual files.
The use of wildcard in makefiles is a bad idea - it is best to list your files explicitly, as I have shown.
Please consult my answer
makefile enforce library dependency ordering
for a discussion of good practices, including phony and real targets.
MAKEFILE := $(lastword $(MAKEFILE_LIST))
CFILES := \
loadStoreByte.c \
string.c \
lib_uart.c \
bubble_uart.c
SFILE_OUTPUT := bubble_uart.s
SFILES := $(SFILE_OUTPUT) \
startup.s \
handler.s
OFILES := $(SFILES:s=o)
APP := bubble_uart
.PHONY: all
all: $(APP)
$(APP): browtb.x $(OFILES) $(MAKEFILE)
gcc-elf-ld -o $# -T $< $(OFILES)
$(OFILES): %o : %s $(MAKEFILE)
gcc-elf-as -o $# $<
$(SFILE_OUTPUT): $(CFILES) $(MAKEFILE)
gcc-elf-gcc -S -combine $(CFILES) -o $#
It is usually best if the target of a rule is the name of the file the rule produces.
So the compile rule:
compile: $(CFILE)
$(CC) -S -combine $^ -o $(APP).s
should be this:
$(APP).s: $(CFILE)
$(CC) -S -combine $^ -o $#
Likewise the object rule:
%: %.s compile
$(AS) -o $#.o $<
should be this:
%.o: %.s
$(AS) -o $# $<
(There's no reason for it to depend on compile or $(APP).s, since bubble_uart.s is irrelevant to most object files.)
Then the list of object files should include bubble_uart.o:
SFILES = $(sort $(wildcard *.s) $(APP).s)
OFILES = $(patsubst %.s,%.o,$(SFILES))
(The sort is to remove duplicates.) Note that this is the list of object files needed for construction of the executable, not the list of object files that happen to exist at the beginning of the build process.
Finally, the executable:
$(APP): $(OFILES)
$(LK) -o $# -T browtb.x $^

makefile automatic variable for corresponding c file

i hava a makefile something like this:
outdir = release
allsrc = aaa/a.c bbb/b.c ccc/c.c
allobjs = $(addprefix $(outdir), $(notdir $(allsrc:.c=.o))
...
test: $(allobjs)
$(allobjs): $(allsrc)
gcc -c -o $# $<
make test performs:
gcc -c -o release/a.o aaa/a.c
gcc -c -o release/b.o aaa/a.c
gcc -c -o release/c.o aaa/a.c
(automatic variable $< always takes first prerequisite)
but i want "corresponding one":
gcc -c -o release/a.o aaa/a.c
gcc -c -o release/b.o bbb/b.c
gcc -c -o release/c.o ccc/c.c
what should i change to accomplish desirable result?
i know that this will work for sure:
$(outdir)/a.o: aaa/a.c
gcc -c -o $# $<
$(outdir)/b.o: bbb/b.c
gcc -c -o $# $<
$(outdir)/c.o: ccc/c.c
gcc -c -o $# $<
and wondering how to accomplish the same in one receipe. (because in my real makefile i have ~20 different source files not just 3 like i made here for example)
You don't write your recipe like that. That's not how make works.
That recipe says that every item in $(allobjs) has every item in $(allsrc) as its prerequisite but that's not what you mean.
You mean that every .o file has the matching .c file as its prerequisite which is exactly what the built in %.o: %.c rule already does. You don't even need a makefile to do that.
Edit: Actually, you don't mean that. I had missed that the source files were in different directories. That changes and complicates things.
Chris Dodd wrote up two good solutions for this.
The usual way to do what you are asking would be something like:
outdir = release
allsrc = aaa/a.c bbb/b.c ccc/c.c
allobjs = $(addprefix $(outdir), $(notdir $(allsrc:.c=.o)))
VPATH = $(sort $(dir $(allsrc)))
...
test: $(allobjs)
$(outdir)/%.o: %.c
gcc -c -o $# $<
Of course, this will run into problems if you have a b.c in both aaa and bbb, but since you're trying to put all the object files in the same directory, you have that regardless. It might make more sense to get rid of the $(notdir and keep the same directory structure under $(outdir), in which case you don't need the VPATH
outdir = release
allsrc = aaa/a.c bbb/b.c ccc/c.c
allobjs = $(addprefix $(outdir), $(allsrc:.c=.o))
...
test: $(allobjs)
$(outdir)/%.o: %.c
mkdir -p `dirname $#`
gcc -c -o $# $<

Fortran90 Makefile with pre-compilation and modules

I'm trying to write a Makefile to compile a Fortran90 project that consists of several source files containing subroutines and modules. To make things more complicated, I'm using pre-compilation (creating *.for files from *.F files). I could not find any answer to this, but this may be because I get confused by the different styles of Makefile syntax.
I created a stripped-down version for reproducing my problem (available on https://github.com/stineb/stackoverflow). This contains a main program (sayhello.F), two subroutines in separate source files (schleppe.F and schnuppi.F), and two modules in separate source files (words_schleppe.mod.F and words_schnuppi.mod.F). The executable is hello.
I am able to build it with a simple Makefile and avoiding the pre-compilation. This file (Makefile_simple) looks like this:
FCOM=gfortran
EXE = hello
standard:
$(FCOM) -c words_schleppe.mod.F
$(FCOM) -c words_schnuppi.mod.F
$(FCOM) -c schleppe.F
$(FCOM) -c schnuppi.F
$(FCOM) words_schleppe.mod.o words_schnuppi.mod.o schleppe.o schnuppi.o sayhello.F -o $(EXE)
.PHONY: clean
clean:
rm $(EXE) *.o *.mod
However, my project will be a bit bigger than this so I want to make use of the cryptic features of a more complex Makefile for defining rules. And crucially: I want to pre-compile source files *.F into .for. This is where I haven't managed to define the rules to create the .mod files from the modules and build the whole thing. Disregarding the modules, I do get it running with the following Makefile (Makefile_complex on my github repository):
FCOM=gfortran
CPPFLAGS=-e
COMPFLAGS=
EXE=hello
SOURCES=sayhello.F schleppe.F schnuppi.F
OBJS=$(SOURCES:.F=.o)
all: $(OBJS)
# this may also be replaced by the ar command (creating archive)
$(FCOM) $(OBJS) -o $(EXE)
%.for: %.F
rm -f $*.for
$(FCOM) $(CPPFLAGS) $*.F > $*.for
$(OBJS): %.o: %.for
$(FCOM) -c -o $# $(COMPFLAGS) $*.for
# clean: remove .for, .o, .do, and .stb files
.PHONY: clean
clean:
-rm -f *.for *.o *.stb *.mod
What do I have to add to this in order to include the modules in the build? The dependencies are as follows: subroutine schleppe <- module words_schleppe; and subroutine schnuppi <- module words_schnuppi.
Help, anyone?
Thanks a bunch!
I FOUND THE SOLUTION! Simply, the rule for all: must include the module source files, and these must precede the other source files. Plus, rules of creating the object files from the module source files have to be added. The working Makefile looks like this:
FCOM=gfortran
CPPFLAGS=-E
COMPFLAGS=
EXE=hello
SOURCES=sayhello.F schleppe.F schnuppi.F
MODS=words_schleppe.F words_schnuppi.F
OBJS=$(SOURCES:.F=.o)
MODOBJS=$(MODS:.F=.o)
# this may also be replaced by the ar command (creating archive)
all: $(MODOBJS) $(OBJS)
$(FCOM) $(OBJS) $(MODOBJS) -o $(EXE)
%.for: %.F
rm -f $*.for
$(FCOM) $(CPPFLAGS) $*.F > $*.for
$(MODOBJS): %.o: %.for
$(FCOM) -c -o $# $(COMPFLAGS) $*.for
$(OBJS): %.o: %.for
$(FCOM) -c -o $# $(COMPFLAGS) $*.for
# clean: remove .for, .o, .do, and .stb files
.PHONY: clean
clean:
-rm -f *.for *.o *.stb *.mod

Makefile include file for same targets

I have a large project using recursive Make. Almost all the Makefiles are the same though. I'm basically building all the object files into the same directory like this:
$(OBJ)/%.o: %.c
$(COMPILE) ${INCLUDES} -c $< -o $#
$(OBJ)/%.o: %.cpp
${CXX} ${INCLUDES} ${FLAGS} -c -fPIC $< -o $#
Is it possible to put these targets in an include file so I don't have to put the same lines in every Makefile?
include I've only used for shared variables and when I tested this using include it did not work.

Resources