Two targets with no dependencies - bash

Consider the following makefile:
TARGET=fmake
TARGET2=test_second
fmake: $(TARGET2).c foo.c\
$(TARGET).c test.h clean
$(CC) -o $(TARGET) $(TARGET).c foo.c
$(CC) -o $(TARGET2) $(TARGET2).c
foo.c:
echo Some text
clean:
rm -f fmake test_second
CC=$(VAR2)
VAR2=gcc
After the make bash command the following display
rm -f fmake test_second
gcc -o fmake fmake.c foo.c
gcc -o test_second test_second.c
As said here foo.c doesn't processed because there is no dependencies for this target. But both foo.c and clean have no dependencies, but clean is processed. Why?

Because a file called foo.c exists, whereas no file called clean exists. So Make thinks that one needs to be made. Note that clean should really be declared as a phony target.

Related

BSD make & GNU make

I have Makefile. This runs on FreeBSD with gmake and make. In BSD Make command not output log same with gmake.
$ gmake
compile main.cpp
linking myout
$ make
c++ -O2 -pipe -c main.cpp -o main.o
linking myout
$ cat Makefile
TARGET = myout
default: $(TARGET)
SRCS = main.cpp
OBJS = $(SRCS:%.cpp=%.o)
default: $(BIN)
%.o: %.cpp
#echo compile $<
#$(CXX) -c $< -o $#
$(TARGET): $(OBJS)
#echo linking $#
#$(CXX) $(OBJS) -o $#
clean:
#rm -f $(OBJS) $(TARGET)
According to the FreeBSD make documentation, it doesn't support pattern rules. So your rule here:
%.o: %.cpp
#echo compile $<
#$(CXX) -c $< -o $#
in FreeBSD make is just an explicit rule telling make how to build the literal file %.o from the literal file %.cpp. Since you don't try to build a file named %.o (you're trying to build main.o), this rule is ignored / never used.
It looks like if you want something that will work the same way between both versions of make you'll have to restrict yourself to the POSIX standard suffix rules format, like this:
.SUFFIXES: .cpp .o
.cpp.o:
#echo compile $<
#$(CXX) -c $< -o $#
The default build utilities are different. FreeBSD uses a different implementation of make than GNU/Linux. The respective man pages outline differences.
https://forums.freebsd.org/threads/difference-gmake-gnu-and-freebsd-make.28784/

How to write a makefile for Fortran with modules?

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

Makefile - a command in a command?

I have an embarrassingly simple makefile question but I can't google it due to lack of knowledge - I don't know the words for things I don't know.
Basically, I want to run the makefile in the current directory, look into the ./SRC directory for source files and when everything is finished, move the object files into the ./OBJ directory.
Makefile:
move_obj:
mv -f -t ./OBJ_DIR ./$(OBJ_FILES)
file.o: other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
move_obj
I want to call "move_obj" after compiling the source files but since I don't know what
result: dependency
evaluation
actually represents (and all makefile introduction guides I've found state "This is what a makefile looks like, off you go then"), I don't know why this isn't working. I assume I need some evaluate command or need to define a function or...?
Thanks for any help in advance.
You can do this by creating another rule for example move, like below
all: $(EXECUTABLE) move
$(EXECUTABLE): $(OBJECTFILES)
$(CC) -o $# $<
$(OBJECTFILES): $(SOURCEFILES)
$(CC) $(CFLAGS) -c -o $# -I $(INCLUDE_PATH) $<
# Move the .o to Object directory #
move:
$(MV) $(OBJECTFILES) $(OBJECT_PATH)
But by doing the above, you will defeat the purpose of the Makefile.
Since your rule is dependent on .o, Make will look for .o in current directory and not find it (because you've moved it) and thus rebuild.
To avoid this, you should output it to ./obj directory and use it from there.
Something like
gcc -g -Wall -o obj/foo.o -c src/foo.c -I ./include
gcc -g -Wall -o obj/main.o -c src/main.c -I ./include
gcc -o exe obj/foo.o obj/main.o -lanylibrary
Below is the makefile doing the same.
C_FLAGS := -g -Wall -Wextra
CC := gcc
RM := rm
LINKFLAGS := -lanylibrary
.PHONY: $(TARGET) clean
VPATH:= ./src/ ./obj/ ./include/
# Path for .c , .h and .o Files
SRC_PATH := ./src/
OBJ_PATH := ./obj/
INC_PATH := -I ./include
# Executable Name
TARGET := exe
# Files to compile
OBJ1 := foo.o \
main.o
OBJ := $(patsubst %,$(OBJ_PATH)%,$(OBJ1))
# Build .o first
$(OBJ_PATH)%.o: $(SRC_PATH)%.c
#echo [CC] $<
#$(CC) $(C_FLAGS) -o $# -c $< $(INC_PATH)
# Build final Binary
$(TARGET): $(OBJ)
#echo [INFO] Creating Binary Executable [$(TARGET)]
#$(CC) -o $# $^ $(LINKFLAGS)
# Clean all the object files and the binary
clean:
#echo "[Cleaning]"
#$(RM) -rfv $(OBJ_PATH)*
#$(RM) -rfv $(TARGET)
Refer to this answer for a better understanding
EDIT:
You can also output your executable to directory, add the following changes to your Makefile.
Ensure that the bin directory is created beforehand, and not deleted by clean.
# Path for .c , .h and .o Files, and ./bin directory
BIN_PATH := ./bin
# Executable Name
TARGET := $(BIN_PATH)/exe
# Clean all the object files and the binary
clean:
#echo "[Cleaning]"
#$(RM) -rfv $(OBJ_PATH)*
#$(RM) -fv $(TARGET)
If you want to build a target(move_obj) after another(file.o), add the move_obj to the dependency list of file.o so that the commands under the move_obj will be executed.
So your Makefile should be:
file.o: other_file.h move_obj
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
move_obj:
mv -f -t ./OBJ_DIR ./$(OBJ_FILES)
As Colonel Thirty Two mentioned in the comment section, instead of compiling and then move, you can build the object files in the required directory
file.o: other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o ./$(OBJ_FILES)/$#
This is flawed in various ways.
result normally is an actual file that should be present after the recipe is executed. If the file is already there and is not older than any of its dependencies, make does nothing. So instead of creating a file somewhere and then moving it around with another rule, make sure the rule creates it where it should FINALLY be. Otherwise make can never check whether it has to rebuild it (and always will). In this case, use the -o flag of the compiler to directly create it where it should be (e.g. -o $(OBJ_DIR)/file.o)
dependency should list ALL files that are needed to build the result, so make really rebuilds it if ANY of these files changed. In your case, at least file.c is missing from the dependency list
In order to place files in a directory, you should make sure it exists. you could do it like this:
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
$(OBJ_DIR)/file.o: $(OBJ_DIR) file.c other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o $(OBJ_DIR)/file.o
Your move_obj recipe, although not suitable in this case, would be a PHONY target, meaning it does not create a file. If you need such rules, mark them accordingly by mentioning them as dependency of the special target .PHONY:
.PHONY: move_obj
The reason for this is that you could (by accident) have a file named move_obj in your working directory. In that case, make would decide there's nothing to do for move_obj, and this is not what you want. Marking it as phony tells make that this rule does not create its target and the recipe must be executed no matter what.
All in all, your question comes down to misunderstanding a Makefile as kind of a script. It is not. It's a declarative file that tells make what has to be done in order to build files (your evaluation block) and when this needs to be done (your dependency block). It's better not to try to misuse a Makefile as a script.

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 as a dependency for a make target

Is it ever a bad idea to include a Makefile as a dependency for a make target?
Eg.
hello.o: hello.cxx Makefile
$(CXX) -c $(CFLAGS) $< -o $#
That way anytime the Makefile is modified the target is recompiled.
No its not a bad idea. Conventionally we never do that but if you have makefile calling other makefile then including it would be a great idea though.
I believe what you're trying to do is run clean (or other equivalent target) whenever the Makefile gets modified.
This can be achieved so. (I've been using this recipe in couple of my C/C++ projects).
CLEANUP_TRIGGER := .makefile
BASE_MAKEFILE := $(firstword $(MAKEFILE_LIST))
FINAL_TARGET := hello.o
all: $(CLEANUP_TRIGGER) $(FINAL_TARGET)
hello.o : hello.c
$(CXX) -c $(CFLAGS) $< -o $#
$(CLEANUP_TRIGGER): $(BASE_MAKEFILE)
if [ -f $(CLEANUP_TRIGGER) ]; then $(MAKE) clean; fi
touch $#
clean:
rm -rf *.o
rm -f $(CLEANUP_TRIGGER)
.PHONY: all clean
The essence is to make sure CLEANUP_TRIGGER is part of the rules which get invoked commonly, run make clean whenever Makefile is newer than CLEANUP_TRIGGER.

Resources