makefile putting objs in separate directory - makefile

Why does
$(OBJDIR)\%.o:$(SRDDIR)\%.s
$(GCC) -c -g -I$(SRCDIR) $(ASFLAGS) $< -o $#
$(OBJDIR)\%.o:$(SRDDIR)\%.c
$(GCC) -c -g -I$(SRCDIR) $(CFLAGS) $< -o $#
gives warning (says ignoring the first rule)
where as
%.o:%.s
$(GCC) -c -g -I$(SRCDIR) $(ASFLAGS) $< -o $#
%.o:%.c
$(GCC) -c -g -I$(SRCDIR) $(CFLAGS) $< -o $#
works fine but I will have all my sources and objs in the same directory.
I would like to put the objs (generated from assembly files and c files) in a separate directory( and I am running make on windows).

Try using forward slashes ("/") instead of backward ones ("\").

The -o flag of GCC determines where the output file are made.
So this may work if you change:
%.o:%.s $(GCC) -c -g -I$(SRCDIR) $(ASFLAGS) $< -o $#
TO
%.o:%.s $(GCC) -c -g -I$(SRCDIR) $(ASFLAGS) $< -o myoutputdir/$#

Related

Makefile with `ifeq` test for specific file

I am trying to set an if test for a specific file in my Makefile to compile it with different flags:
.f90.o:
ifeq ($<,main.f90)
#echo ok $<
$(F90) -c $< -o $#
else
#echo nope $<
$(F90) $(F90FLAGS) $(DEBUG) $(INCL) -c $< -o $#
endif
..and despite my efforts I am getting only:
nope main.f90
mpif90 -O2 -g -fbacktrace -fPIC -c main.f90 -o main.o
The ifeq conditional you have used is processed by Make at parse time, not when the recipe is executed. The macro $< is empty when your script is parsed so your recipe only ever contains the latter two lines.
One solution is to provide two recipes, one for your special case and then a pattern recipe for the rest:
main.o:main.f90
$(F90) -c $< -o $#
.f90.o:
$(F90) $(F90FLAGS) $(DEBUG) $(INCL) -c $< -o $#

Compiling with nvcc and g++

I'm using Nvidia's nvcc compiler to compile a .cpp file which will contain device code (but only contains host code now). The program I am using is written in C and C++ and uses gcc/g++ to compile with and g++ is used to link the final executable together. Originally, when I run my program using -Ofast, it runs in about 2 seconds, but I factored in nvcc to compile 1 .cpp file and the rest with gcc/g++, have g++ link it together, the program takes about 8 seconds to run. If I compile more .cpp files with nvcc, it slows down even more (~10 seconds). I tried adjusting my make file to compile everything with nvcc but I received too many errors from the C code. Only the C++ code seems to be able to run without errors when compiled with nvcc. Does nvcc not optimise the host code? Why does this happen? What is the best way to structure the program?
Makefile
CC = gcc
CCPP = g++
NVCC = /vol/cuda/8.0.61/bin/nvcc
#preprocessor defines
DEFINES = -DUSE_ZLIB
OPTFLAGS = -Ofast
#CFLAGS = -ansi -pedantic -Wall -Werror -fPIC
#CFLAGS = -ansi -pedantic -Wall -fPIC
CFLAGS = -ansi $(OPTFLAGS)
NVFLAGS = -x c++ -Wno-deprecated-gpu-targets -ccbin g++
NVLINKFLAGS = -L/vol/cuda/8.0.61/lib64/ -lcuda -lcudart
#NVLINKFLAGS += -L/vol/cuda/8.0.61/lib -lcuda -lcudart
CPPFLAGS = $(OPTFLAGS) -I./include $(DEFINES)
LINKFLAGS = -lz
all : simple
objs = src/tourtre.o \
src/ctArc.o \
src/ctBranch.o \
src/ctComponent.o \
src/ctNode.o \
src/ctQueue.o \
src/ctNodeMap.o \
examples/simple/obj/Data.o \
examples/simple/obj/Mesh.o \
examples/simple/obj/main.o
simple : $(objs)
$(CCPP) $(CPPFLAGS) -o simple $^ $(LINKFLAGS) $(NVLINKFLAGS)
src/tourtre.o : src/tourtre.c include/tourtre.h src/ctMisc.h include/ctArc.h include/ctNode.h src/ctComponent.h include/ctNode.h src/ctQueue.h src/ctAlloc.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctArc.o : src/ctArc.c include/tourtre.h src/ctMisc.h include/ctArc.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctBranch.o : src/ctBranch.c include/tourtre.h src/ctMisc.h include/ctBranch.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctComponent.o : src/ctComponent.c include/tourtre.h src/ctMisc.h src/ctComponent.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctNode.o : src/ctNode.c include/tourtre.h src/ctMisc.h include/ctNode.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctQueue.o : src/ctQueue.c include/tourtre.h src/ctMisc.h src/ctQueue.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
src/ctNodeMap.o : src/ctNodeMap.c src/ctNodeMap.h include/ctNode.h src/ctQueue.h src/sglib.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
examples/simple/obj/Data.o: examples/simple/src/Data.cpp examples/simple/src/Data.h examples/simple/src/Global.h
$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
examples/simple/obj/Mesh.o: examples/simple/src/Mesh.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h
$(NVCC) $(NVFLAGS) -c $< -o $#
examples/simple/obj/main.o: examples/simple/src/main.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h
$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
clean :
-rm -rf src/*.o examples/simple/obj/*.o doc/html
Add -Xcompiler -ansi -Xcompiler -Ofast to NVFLAGS so that the host compiler gets the same (optimization) flags from nvcc as when run directly.

Makefile causes `gfortran: error: No such file or directory`

I am trying to compile this code with gfortran.
Makefile:
# makefile for BIRRP
FC = gfortran
FCFLAGS = -g -fbounds-check
FLFLAGS = -g -fbacktrace
SRC = birrp.f coherence.f dataft.f diagnostic.f fft.f filter.f math.f rarfilt.f response.f rtpss.f utils.f weight.f zlinpack.f
# "make" builds all
PROGRAM = birrp
all: $(PROGRAM)
$(PROGRAM): $(SRC)
$(FC) $(FCFLAGS) $# $<
%.o: %.f
$(FC) $(FLFLAGS) -o $# $^
clean:
rm -f *.o
It doesn't work
gfortran -g -fbounds-check birrp birrp.f
gfortran: error: birrp: No such file or directory
Makefile:13: recipe for target 'birrp' failed
make: *** [birrp] Error 1
I am using the gfortran compiler. I have copied the Makefile from my other program.
After adding -o:
FC = gfortran
FCFLAGS = -g -c -fbounds-check
FLFLAGS = -g -fbacktrace
SRC = birrp.f coherence.f dataft.f diagnostic.f fft.f filter.f math.f rarfilt.f response.f rtpss.f utils.f weight.f zlinpack.f
# "make" builds all
PROGRAM = birrp
all: $(PROGRAM)
$(PROGRAM): $(SRC)
$(FC) $(FCFLAGS) -o $# $<
%.o: %.f
$(FC) $(FLFLAGS) -o $# $^
clean:
rm -f *.o
Now it just compiles
gfortran -g -c -fbounds-check -o birrp birrp.f
Why?
gfortran interprets birrp as a source-file, but you want it as the outfile.
man gfortran
says the outfile is specified by the -o parameter, so your target becomes this:
$(PROGRAM): $(SRC)
$(FC) $(FCFLAGS) -o $# $<
But this doesn't solve all your problems. According to the GNU Make manual $< specifies the first dependency and not all of them. You always want to have the whole list of dependencies, which would be $^.
So your target becomes this:
$(PROGRAM): $(SRC)
$(FC) $(FCFLAGS) -o $# $^

gcc cannot specify -o with -c or -S with Multiple files

Whenever I am trying to build something like this in my Makefile -
gcc -o main.o -IStarterWare_Files -c main.c StarterWare_Files/test.h StarterWare_Files/add.h
It throws me error that gcc: cannot specify -o with -c or -S with multiple files. Basically I want my makefile to build the target again if I change for example some macro in one of my header files. My current Makefile is -
EXE = nextgenrsm
CC = gcc
LIBS = StarterWare_Files/
CPPFLAGS = _IStarterWare_Files/
MAIN_OBS = $(patsubst %.c,%.o,$(wildcard *.c))
LIB_OBS = $(patsubst %.c,%.o,$(wildcard StarterWare_Files/*.c))
all: $(EXE)
$(EXE): $(MAIN_OBS) $(LIB_OBS)
$(CC) -o $# $(LDFLAGS) $(MAIN_OBS) $(LIB_OBS) $(LDLIBS)
%.o: %.c
$(CC) -o $# -MD -MP $(CPPFLAGS) $(CFLAGS) -c $^
ALL_DEPS = $(patsubst %.o,%.d,$(MAIN_OBS), $(LIB_OBS))
-include $(ALL_DEPS)
clean:
rm -f $(LIB_OBS) $(EXE) $(MAIN_OBS) $(ALL_DEPS)
.PHONY: all clean
I can't figure out what changes to make to build my executable again if one of the header files is modified. I don't want to do make clean and make again.
The way the automake system handles this is to not use %.o: %.c but instead list the C file and all of the headers in the C file.
So for example:
main.o: main.c StarterWare_Files/test.h StarterWare_Files/add.h
$(CC) -o $# -MD -MP $(CPPFLAGS) $(CFLAGS) -c $^
See makedepends for a tool that will read C files and figure out the make dependencies.

How to make specific binary from specific object file?

Here is my makefile, i have object files in obj/ directory, and i need to compile them into binaries in bin/ folder, but somehow it doesn't work as i wanted it to work, any ideas?
SOURCES= $(wildcard *.c)
OBJECTS:= $(patsubst %.c, %.o, $(SOURCES))
OBJECTS:= $(addprefix obj/,$(OBJECTS))
NAMES:= $(patsubst %.c, %, $(SOURCES))
NAMES:= $(addprefix bin/,$(NAMES))
CC=gcc
CFLAGS= -Wall -c -o
DIRS = bin obj
all: $(DIRS) $(NAMES)
$(NAMES): $(OBJECTS)
$(CC) -o $# $<
obj/%.o: %.c
$(CC) $(CFLAGS) $# $<
$(DIRS):
mkdir -p $#
clean:
rm -rf $(DIRS)
Actual output:
mkdir -p bin
mkdir -p obj
gcc -Wall -c -o obj/task1.o task1.c
gcc -Wall -c -o obj/task2.o task2.c
gcc -Wall -c -o obj/task3.o task3.c
gcc -o bin/task1 obj/task1.o
gcc -o bin/task2 obj/task1.o
gcc -o bin/task3 obj/task1.o
Expected output:
mkdir -p bin
mkdir -p obj
gcc -Wall -c -o obj/task1.o task1.c
gcc -Wall -c -o obj/task2.o task2.c
gcc -Wall -c -o obj/task3.o task3.c
gcc -o bin/task1 obj/task1.o
gcc -o bin/task2 obj/task2.o
gcc -o bin/task3 obj/task3.o
In this rule:
$(NAMES): $(OBJECTS)
$(CC) -o $# $<
each executable depends on all objects. And since $< grabs only the first prerequisite, all you see is obj/task1.o.
Do it this way:
bin/%: obj/%.o
$(CC) -o $# $<
or this way:
$(NAMES): bin/% : obj/%.o
$(CC) -o $# $<

Resources