continuation in compiler flag of make file - makefile

is there any way to have multi-line compiler flags in a make file?
I tried the following:
EXECUTABLE= test
SOURCES= test.f90
OBJECTS=$(SOURCES: .f90=.o)
FFLAGS= -fast -vec-report=3 -profile-functions \ # enable for profiling
-profile-loops=all -profile-loops-report=2
FC=/opt/intel/bin/ifort
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(FC) $(FFLAGS) $(LDFLAGS) $(OBJECTS) -o $#
clean:
rm -f core *~ *.o $(EXECUTABLE)
but it cuts off the second line of FFLAGS

You had the right idea. You just then shot yourself in the foot.
A trailing \ is the correct solution you just then proceeded to put more data on the line thus negating the "trailing" part of the continuation marker. Move that comment and it will work.

Related

Quiet makefile not working

So I've a recursive makefile that's on a project, but for some reason, AR is the only command that still prints output.
How can I force it to be quiet? It has already '#' at the beginning, and I don't want to pipe the output to null.
How i'm calling this makefile?
#cd libc; make clean --no-print-directory
Here's the troublemaker makefile:
include ../Makefile.inc
LIB=../libc.a
SOURCES=$(wildcard *.c)
SOURCES_ASM=$(wildcard asm/*.asm)
OBJECTS=$(SOURCES:.c=.o)
OBJECTS_ASM=$(SOURCES_ASM:.asm=.o)
all: $(LIB)
#echo -e " libC [ \033[0;32mOK \033[0m]"
$(LIB): $(OBJECTS) $(OBJECTS_ASM)
#$(AR) $(ARFLAGS) -c $(LIB) $(OBJECTS_ASM) $(OBJECTS)
$(OBJECTS): $(SOURCES)
$(OBJECTS_ASM): $(SOURCES_ASM)
%.o: %.c
#$(GCC) $(GCCFLAGS) -c $< -o $#
%.o: %.asm
#$(ASM) $(ASMFLAGS) $< -o $#
clean:
#rm -rf *.o ../*.a
.PHONY:
all clean
and here's the output:
a - asm/syscall.o
a - syscall.o
a - string.o
a - stdio.o
a - integer.o
libC [ OK ]
Thanks in advance
If you don't want ar to print output then stop telling it to do so! :)
Since you haven't shown any setting for ARFLAGS I assume you're using the default value, which in GNU make is rv and the v flag means "verbose" (see man ar).
So, just setting:
ARFLAGS = r
in your makefile should turn off the verbose output from ar.
I suggest you to simply redirect the stdout to a log file for AR command only, as follows:
#$(AR) $(ARFLAGS) -c $(LIB) $(OBJECTS_ASM) $(OBJECTS) >> $(LOG_FILE)
It keeps the errors displayed because it does not redirect stderr.

Why I don't need to add prerequisite ".depend" in this make file?

I have a make file I wrote which represents a simple example of auto-detecting if a header file is changed using .depend generated by gcc -MM -MF.
Consider the following makefile: We have main.c and factorial.h
CC=gcc
CFLAGS=-c -Wall
OBJECTS=main.o
SRCS=main.c
EXECUTABLE=program
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) -o $(EXECUTABLE)
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
sinclude .depend
#main.o: main.c factorial.h
clean:
rm -rf *.o $(EXECUTABLE) .depend
This works fine and I want to know why!
The common sense is to write
$(EXECUTABLE): $(OBJECTS) .depend
because we want to make sure the file .depend is there. However, it seems like omitting it works fine, too. Why? Also, I'd like to know what include (or sinclude in this case) actually does. I think: in our example, include .depend would be replaced by
main.o: main.c factorial.h, but again the workflow doesn't make sense. Any experts?
Make will automatically try to remake the target of an include directive
[...]after reading in all makefiles, make will consider each as a goal target and attempt to update it.
The line sinclude .depend tells make "Read in .depend, don't quit if it fails, look for any matching rules, and remake .depend if it's out of date."
In any case you should create dependencies as a side effect of compilation, there's really no need for the extra step
target := program
sources := main.c
objs := $(sources:.c=.o)
deps := $(objs:.o=.d)
CPPFLAGS := -MMD -MP
CFLAGS := -Wall
$(target): $(objs)
$(LINK.o) $^ $(LDLIBS) -o $#
clean: ; $(RM) $(target) $(objs) $(deps)
-include $(deps)

How can I put .o files to different folder and how should I improve this overall?

I've never really wrote any makefiles before and I have little knowledge of its syntax.
I'd like to put .o files into separate folder, obj/ for example. But I'm a bit lost how this should be done since there seem to be lot's of different ways to write makefile.
This is what I have currently and I would like to improve it.
PROGRAM=Project
CC=g++
CFLAGS=-c -g -std=c++0x -Wall -Wextra -pedantic -I $(SFML)/include -I src
LDFLAGS=-lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio -L $(SFML)/lib -Wl,-rpath=$(SFML)/lib -Wl,-rpath-link=$(SFML)/lib
SOURCES=$(wildcard src/*.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=bin/project
all: build $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
build:
#mkdir -p bin
clean:
rm -rf $(EXECUTABLE) $(OBJECTS)
I've tried some different approaches but haven't yet figured out how to put .o files in their own folder.
Replace your OBJECTS line with something like:
OBJECTS=$(patsubst src/%.cpp,obj/%.o,$(SOURCES))
Remove the .ccp.o rule and replace it with something like:
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) $< -o $#
You can probably also remove $(SOURCES) from the prerequisite list of the all target unless you expect make to try to create those files somehow.

Multiple Rules for Single Target -- Doesn't Work as Expected

Here's a shortened version of the Makefile I am fighting with on a Linux system:
VPATH=altsrc:src:obj
OBJECTS=\
nondepcode1.o \
nondepcode2.o \
nondepcode3.o \
depcode1.o \
depcode2.o \
depcode3.o
DEP_OBJS= depcode1.o depcode2.o depcode3.o
# Targets
execute: $(OBJECTS)
gfortran -o $# $^ $(LFLAGS)
$(DEP_OBJS): npts.h
obj/%.o: %.f
$(FORTRAN) $(FFLAGS) $< -o $#
obj/%.o: %.f90
$(FORTRAN) $(FFLAGS) $< -o $#
# Rules
.f.o:
$(FORTRAN) $(FFLAGS) -o obj/$# $<
%.o: %.f90
$(FORTRAN) $(FFLAGS) -o obj/$# $<
I was expecting that the three objects that depend on "npts.h" would be automatically updated on a run of make (or gmake) if npts.h was more recent than any of the objects. This just does not happen. Make (and gmake) thinks the objects are up to date. AFAICT, I am doing things the way they are described in the GNU make manual. Anyone have any idea why make/gmake is not doing what I expected? Thanks. BTW, there are tabs at the beginning of all the recipe lines in the actual Makefile. They went away here.
Major egg on my face. As I said, this was a shortened version of the Makefile. I found the bug in the real Makefile. Had some misnamed macros. Not too experienced with the finer points of this stuff. Mea culpa. Very sorry. Thanks for checking.

Could someone explain this make file?

I found this makefile on this site. They don't explain this example, so I was wondering if anybody new what was going on.
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
sets four variables to be constant strings. For the rest of the makefile, wherever $(CC) appears (for example), it will be replaced by g++
OBJECTS=$(SOURCES:.cpp=.o)
sets the variable OBJECTS to be the same as SOURCES, except wherever the pattern .cpp appears in a words of SOURCES, its replaced by .o
EXECUTABLE=hello
sets another constant string var
all: $(SOURCES) $(EXECUTABLE)
The first actual rule in the makefile, This tells make that to build all it must first build everything in $(SOURCES) and $(EXECUTABLE), and then do nothing. Since this is first, it becomes the default target, so running make is equivalent to make all
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
Another rule: to create $(EXECUTABLE) (which expands to hello) it must first build everything in $(OBJECTS) (equivalent to main.o hello.o factorial.o) and then run the command $(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) -o $# $<
A pattern rule: in order to build a file ending in .o, first rebuild/create/find the corresponding file ending in .cpp, and then run the command $(CC) $(CFLAGS) -o $# $<.
These last two rules contain the special variables $# and $< which are only valid in rule actions and expand to the target and first dependency respectively
So when you run make, it reads all this and then tries to build the default target (all).
Since it doesn't exist, it tries to build the files main.cpp, hello.cpp, factorial.cpp, and hello. Since the first 3 (presumably) exist, it looks for rules/dependencies for them, but doesn't find any, so decides there's nothing to do for them. If they didn't exist, make would give an error saying "no rule to make target 'main.cpp'"
In the case of "hello" it depends on main.o, hello.o and factorial.o, so it looks into them. For main.o, the pattern rule says it depends on main.cpp, so if main.o doesn't exist or if main.cpp is newer, it will run the command g++ -c -Wall -o main.o main.cpp. The same happens for hello.o and factorial.o.
Once those are done, if hello doesn't exist or is older than any of those .o files (which may have just changed, so are possibly pretty new), it will run that command to relink it. Finally, it will run the empty command (doing nothing) to 'rebuild' all.

Resources