I have the following Makefile which works fine but is not very elegant.
bin/a.gb: obj/main.o obj/i.o obj/in.o obj/g.o obj/an.o obj/s.o obj/b.o obj/b_m.o obj/b_r.o obj/b_e.o
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -o bin/a.gb obj/main.o obj/i.o obj/in.o obj/g.o obj/an.o obj/s.o obj/b.o obj/b_m.o obj/b_r.o obj/b_e.o
obj/main.o: src/main.c include/common.h include/i.h include/in.h include/an.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/main.o src/main.c
obj/i.o: src/i.c include/common.h include/i.h include/b_m.h include/b.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/i.o src/i.c
obj/in.o: src/in.c include/common.h include/in.h include/g.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/in.o src/in.c
obj/g.o: src/g.c include/common.h include/g.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/g.o src/g.c
obj/an.o: src/an.c include/common.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/an.o src/an.c
obj/s.o: src/s.c include/s.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/s.o src/s.c
obj/b.o: src/b.c include/b.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/b.o src/b.c
obj/b_m.o: src/b_m.c include/b_m.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/b_m.o src/b_m.c
obj/b_r.o: src/b_r.c include/b_r.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/b_r.o src/b_r.c
obj/b_e.o: src/b_e.c include/b_e.h
/opt/gbdk/bin/lcc -Iinclude -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug -c -o obj/b_e.o src/b_e.c
.PHONY: clean
clean:
find bin obj -type f \( -name '*.gb' -o -name '*.o' -o -name '*.ihx' -o -name '*.cdb' -o -name '*.map' -o -name '*.noi' -o -name '*.adb' -o -name '*.lst' -o -name '*.sym' -o -name '*.asm' \) -exec rm {} +
In order to make it more streamlined and generalized so that I don't have to edit it as much for every new source file, I came up with the following:
IDIR=include
BDIR=bin
ODIR=obj
SDIR=src
CC=/opt/gbdk/bin/lcc
CFLAGS=-I$(IDIR) -Wa-l -Wl-m -Wl-j -Wl-y -Wl-w -Wf--debug
DEPS := $(wildcard $(IDIR)/*)
_OBJ = an.o b_e.o b_m.o b_r.o b.o g.o i.o in.o main.o s.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: $(SDIR)/%.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$(BDIR)/a.gb: $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(ODIR)/* *~ core $(IDIR)/*~ $(BDIR)/*
This also works. The only drawback so far is that it loses the association of which header files are dependencies for which object files. So with the original Makefile, if I changed the contents of a single header file, only the object files whose sources include that header got rebuilt. But now, if any of the header files are edited, it rebuilds all of the object files. Is there a clever way around this? I'd like for my new, streamlined Makefile to only rebuild the necessary object files if a header file is changed.
I found this solution but I'm having a hard time understanding how to incorporate it into my new Makefile. I don't understand the purpose of the -include $(ODIR)/*.d line, for instance or where that would go.
EDIT: I realize now that the solution that I linked may not work for the lcc compiler, as it does not appear to have the -MMD option (at least as far as I can tell).
You can add any number of extra dependencies to a rule next to the declared recipe:
$(ODIR)/%.o: $(SDIR)/%.c
$(CC) -c -o $# $< $(CFLAGS)
$(ODIR)/an.o: $(DEPS)/dep1.h $(DEPS)/dep2.h $(DEPS)/dep3.h
$(ODIR)/b_e.o: $(DEPS)/dep1.h $(DEPS)/dep3.h
(Using patsubst to reduce the boiler plate left as student exercise)
There is also the .EXTRA_PREREQS variable in GNU Make 4.3, which is more handy when the prerequisites are not meant to be part of the recipe, https://lwn.net/Articles/810071/ :
New feature: .EXTRA_PREREQS variable
Words in this variable are considered prerequisites of targets but they are
not added to any of the automatic variable values when expanding the
recipe. This variable can either be global (applies to all targets) or
a target-specific variable. To detect this feature search for 'extra-prereqs'
in the .FEATURES special variable.
Related
Compiling error
I am quite new to Fortran coding.
Currently, I have a makefile which has been previously used by original authors to compile the Fortran codes in Linux. However, I cannot understand what needs to be changed in the previous makefile to run it in Windows-based compiler Silverfrost FTN95.
While trying to compile in FTN95 I encountered the following error:
C:\Users\Geo-TGS\Documents\landslidemodel\src\TRIGRS>MAKE TPX
mpif90 -w -O3 -w -O3 -c ssizgrd.f95
process_begin: CreateProcess(NULL, mpif90 -w -O3 -w -O3 -c ssizgrd.f95, ...) failed.
make (e=2): The system cannot find the file specified.
makefile:59: recipe for target `ssizgrd.o' failed
MAKE: *** [ssizgrd.o] Error 2
C:\Users\Geo-TGS\Documents\landslidemodel\src\TRIGRS>make trg
mpif90 -w -O3 -w -O3 -c grids.f95
process_begin: CreateProcess(NULL, mpif90 -w -O3 -w -O3 -c grids.f95, ...) failed.
make (e=2): The system cannot find the file specified.
makefile:59: recipe for target `grids.o' failed
make: *** [grids.o] Error 2
Below is the Makefile code:
TRG = trg
PRG = prg
TPX = tpx
OBJT90 = trigrs.o flux.o prpijz.o svxmdv.o svijz.o dzero_brac.o
OBJT95 = grids.o input_vars.o model_vars.o dsimps.o input_file_defs.o iverson.o pstpi.o satfin.o savage.o steady.o trini.o unsinf.o ivestp.o pstpf.o rnoff.o satinf.o smallt.o svgstp.o unsfin.o unsth.o ssizgrd.o svlist.o
OBJT77 = calerf.o dbsct.o derfc.o irdgrd.o irdswm.o isvgrd.o roots.o srdgrd.o srdswm.o ssvgrd.o
OBJP90 = trigrs_p.o partial_p.o flux.o flux_p.o prpijz.o svxmdv.o svijz.o dzero_brac.o srdgrd_p.o irdgrd_p.o
OBJP95 = modules_p.o grids.o input_vars.o model_vars.o dsimps.o input_file_defs.o iverson.o pstpi.o pstpi_p.o satfin.o satfin_p.o savage.o steady.o trini.o trini_p.o unsinf.o unsinf_p.o ivestp.o ivestp_p.o pstpf.o pstpf_p.o rnoff.o satinf.o satinf_p.o smallt.o svgstp.o svgstp_p.o unsfin.o unsfin_p.o unsth.o unsth_p.o ssizgrd.o ssizgrd_p.o svlist.o rnoff_p.o steady_p.o
OBJP77 = calerf.o dbsct.o derfc.o irdgrd.o irdswm.o irdswm_p.o isvgrd.o roots.o srdgrd.o srdswm.o srdswm_p.o ssvgrd.o
OBJX90 = tpindx.o nxtcel.o
OBJX95 = ssizgrd.o
OBJX77 = isvgrd.o mpfldr.o rdflodir.o sindex.o slofac.o srdgrd1.o
LIBS =
CC = gcc -O3
CCFLAGS = -lgsl -lgslcblas -lm
FC = ftn95 -w -O3
FFLAGS =
F90 = f95 -w -O3
MPIF90 = mpif90 -w -O3
F90FLAGS = -w -O3
LDFLAGS = -w -O3
all: $(TRG) $(PRG)
#-----------------------------------------------------------------
$(TRG): $(OBJT95) $(OBJT90) $(OBJT77)
$(F90) $(CCLIBS) $(LDFLAGS) -o $# $(OBJT95) $(OBJT90) $(OBJT77) $(CCFLAGS) $(LIBS)
$(PRG): $(OBJP95) $(OBJP90) $(OBJP77)
$(MPIF90) $(CCLIBS) $(LDFLAGS) -o $# $(OBJP95) $(OBJP90) $(OBJP77)
$(CCFLAGS) $(LIBS)
$(TPX): $(OBJX95) $(OBJX90) $(OBJX77)
$(F90) $(CCLIBS) $(LDFLAGS) -o $# $(OBJX95) $(OBJX90) $(OBJX77) $(CCFLAGS) $(LIBS)
#-----------------------------------------------------------------
clean:
rm -f $(TRG) $(TPX) $(PRG)
rm -rf $(OBJT95) $(OBJT90) $(OBJT77) $(OBJP95) $(OBJP90) $(OBJP77)
rm -rf $(OBJX95) $(OBJX90) $(OBJX77)
rm -rf *.mod *.exe *.stackdump
.SUFFIXES: $(SUFFIXES) .f90 .f .c .f95
.f90.o:
$(MPIF90) $(F90FLAGS) -c $<
.f.o:
$(MPIF90) $(F90FLAGS) -c $<
.c.o:
$(CC) $(CCINCLUDE) -c -w $<
.f95.o:
$(MPIF90) $(F90FLAGS) -c $<
What changes need to be made for the code to compile?
I have the following Makefile. Whenever I run make, I get the following error.
ifort: error #10236: File not found: 'mkl_matrix_multiply.o'
I have been trying to figure this out for a while now with no luck.
C = icc
FC = ifort
LD = ifort
OPT = -Ofast -vec_report6 -simd -xhost -debug -traceback -ftrapuv
OP = -Ofast -vec_report6 -simd -xhost
LINK = -L$(MKLROOT)/lib/intel64 $(MKLROOT)/lib/intel64/libmkl_blas95_ilp64.a -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -lpthread -lm
INCLUDE = -openmp -i8 -I$(MKLROOT)/include/intel64/ilp64 -I$(MKLROOT)/include
mkl_matrix_multiply.exe: mkl_matrix_multiply.o timing.o
$(LD) -o mkl_matrix_multiply.exe mkl_matrix_multiply.o timing.o
mkl_matrix_multiply.o: mkl_matrix_multiply.f90
$(FC) $(INCLUDE) $(LINK) mkl_matrix_multiply.f90
timing.o: timing.c
$(CC) $(OP) -c timing.c
dummy.o: dummy.c
$(CC) $(OP) -c dummy.c
clean:
rm -f *.o matrix_multiply.exe
Any help would be greatly appreciated.
Seems like you are missing -c in mkl_matrix_multiply.o rule.
Modify your makefile as
C = icc
FC = ifort
LD = ifort
OPT = -Ofast -vec_report6 -simd -xhost -debug -traceback -ftrapuv
OP = -Ofast -vec_report6 -simd -xhost
LINK = -L$(MKLROOT)/lib/intel64 $(MKLROOT)/lib/intel64/libmkl_blas95_ilp64.a -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -lpthread -lm
INCLUDE = -openmp -i8 -I$(MKLROOT)/include/intel64/ilp64 -I$(MKLROOT)/include
mkl_matrix_multiply.exe: mkl_matrix_multiply.o timing.o
$(LD) -o mkl_matrix_multiply.exe mkl_matrix_multiply.o timing.o
mkl_matrix_multiply.o: mkl_matrix_multiply.f90
$(FC) -c $(INCLUDE) $(LINK) mkl_matrix_multiply.f90
timing.o: timing.c
$(CC) $(OP) -c timing.c
dummy.o: dummy.c
$(CC) $(OP) -c dummy.c
clean:
rm -f *.o matrix_multiply.exe
I'm getting the following error from my compiler:
g++ -c -m32 tracecone.cpp -I/usr/X11R6/include -I/usr/X11/include/GL -I/Users/owner/Documents/raytrace/Graphics -I../RayTrace -I/Users/owner/Documents/raytrace/Graphics -I/Users/owner/Documents/raytrace/VrMath -I/Users/owner/Documents/raytrace/OpenglRender -I/Users/owner/Documents/raytrace/RaytraceMgr
g++ -o -m32 tracecone ../RayTrace/RayTraceData.o tracecone.o /Users/owner/Documents/raytrace/OpenglRender/GlutRenderer.o /Users/owner/Documents/raytrace/RaytraceMgr/SceneDescription.o -L/usr/X11/lib -L/usr/X11R6/lib -L/Users/owner/Documents/raytrace/Graphics -L/Users/owner/Documents/raytrace/VrMath -lglut -lGLU -lGL -lX11 -lXext -lXmu -lXext -lXmu -lXt -lXi -lSM -lICE -lraygraph -lvrmath
i686-apple-darwin11-llvm-g++-4.2: tracecone: No such file or directory
make: *** [tracecone] Error 1
However, I am not sure which file it's saying is not there. Does it mean tracecone? or one of the library files? Either way, it looks like everything is right where it should be.
What could cause this error?
Here is my make file:
PROG = tracecone
RBASE= /Users/owner/Documents/raytrace
GDIR=$(RBASE)/Graphics
MDIR=$(RBASE)/VrMath
ODIR=$(RBASE)/OpenglRender
MANDIR=$(RBASE)/RaytraceMgr
CFLAGS = -w -s -O2 -ansi -DSHM
XLIBS = -lX11 -lXext -lXmu -lXext -lXmu -lXt -lXi -lSM -lICE
LIBS = -lglut -lGLU -lGL
RAYLIBS = -lraygraph -lvrmath
INCLS = -I/usr/X11R6/include -I/usr/X11/include/GL
INCL1 = -I$(GDIR) -I../RayTrace -I$(GDIR) -I$(MDIR) -I$(ODIR) -I$(MANDIR)
LIBDIR = -L/usr/X11/lib -L/usr/X11R6/lib -L$(GDIR) -L$(MDIR)
#source codes
SRCS = $(PROG).cpp
#substitute .cpp by .o to obtain object filenames
OBJS = $(SRCS:.cpp=.o)
#in ../Graphics
OBJOD = $(ODIR)/GlutRenderer.o
OBJO = GlutRenderer.o
OBJMAND = $(MANDIR)/SceneDescription.o
OBJMAN = SceneDescription.o
OBJ_temp = ../RayTrace/RayTraceData.o
#$< evaluates to the target's dependencies,
#$# evaluates to the target
$(PROG): $(OBJS)
g++ -o -m32 $# $(OBJ_temp) $(OBJS) $(OBJOD) $(OBJMAND) $(LIBDIR) $(LIBS) $(XLIBS) $(RAYLIBS)
$(OBJS):
g++ -c -m32 $*.cpp $(INCLS) $(INCL1)
$(OBJ1):
cd $(GDIR); g++ -m32 -c $*.cpp $(INCLS)
$(OBJM):
cd $(MDIR); g++ -m32 -c $*.cpp $(INCLS)
$(OBJO):
cd $(ODIR); g++ -m32 -c $*.cpp $(INCLS)
$(OBJMAN):
cd $(MANDIR); g++ -m32 -c $*.cpp $(INCLS)
clean:
rm $(OBJS)
clean1:
rm $(OBJD1)
Thanks in advance.
You should place your target right after -o flag:
g++ -o $# -m32 ...
Flag -o means output and in case of g++ -o tracecone ... you'll specify tracecone as output, but in case g++ -o -m32 tracecone ... you are specifying -m32 as output and tracecone as one of the object files. And g++ says that there is no such object file because there is actually no such file.
I have the following make file:
CC = gcc
CCDEPMODE = depmode=gcc3
CFLAGS = -g -O2 -W -Wall -Wno-unused -Wno-multichar
COMPONENTHEADER = Q_OBJECT
CPP = gcc -E
CPPFLAGS = -I/usr/include/Inventor/annex -D_REENTRANT -I/usr/share/qt3/include
CXX = g++
CXXCPP = g++ -E
CXXDEPMODE = depmode=gcc3
CXXFLAGS = -g -O2 -fno-exceptions -W -Wall -Wno-unused -Wno-multichar -Woverloaded- virtual
CYGPATH_W = echo
GUI = QT
Gui = Qt
INCLUDES =
LIBS = -lSoQt -lqt-mt -lXmu -lXi -lCoin -lGL -lXext -lSM -lICE -lX11 -ldl -lpthread -lm -lcxcore -lcv -lhighgui -lcvaux
OBJS = MathTools.o PointCloud.o ExtractFeatures.o Tile.o Shape.o RoadDynamic.o
SRCS = MathTools.cpp PointCloud.cpp ExtractFeatures.cpp Tile.cpp Shape.cpp RoadDynamic.cpp main.cpp
HDRS = constants.h Shape.h MathTools.h PointCloud.h ExtractFeatures.h Tile.h RoadDynamic.h
WIDGET = QWidget *
all: main
main: main.o ${OBJS}
${CC} ${CFLAGS} ${INCLUDES} -o $# main.o ${OBJS} ${LIBS}
.c.o:
${CC} ${CFLAGS} ${INCLUDES} -c $<
depend:
makedepend ${SRCS}
clean:
rm *.o core *~
tar:
tar cf code.tar Makefile *.c *.h testfile1
print:
more Makefile $(HDRS) $(SRCS) | enscript -2r -p listing.ps
I am wondering why when I run make the output is
g++ -g -O2 -fno-exceptions -W -Wall -Wno-unused -Wno-multichar -Woverloaded-virtual -I/usr/include/Inventor/annex -D_REENTRANT -I/usr/share/qt4/include -c -o main.o main.cpp
instead of:
gcc -g -O2 -W -Wall -Wno-unused -Wno-multichar ...
it seems the cxx variables are overriding the cc variables. Why is that?
also what does the "include =" do in this case? It doesn't seem to be set to anything.
Thank you
Because your object files are apparently built from .cpp files. You have no explicit rule for building .o files from .cpp files, so Make uses the implicit rule $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c.
i'm trying to use GCC (linux) with a makefile to compile my project.
I get the following error :
% make map
make: *** No rule to make target `map'. Stop.
Does any one have any idea what could that be ?
This is the makefile:
CC = gcc
DEBUG_FLAG = -g
COMP_FLAG = -std=c99 -Wall -Werror -pedantic-errors -DNDEBUG
LIB = -L. -lmtm
MAP_OBJS = map.o
USER_OBJS = user.o
NETWORK_OBJS = network.o
ISOCIAL_OBJS = network.o user.o Isocial.o
PARSING_OBJS = user.o network.o map.o Isocial.o mtm_isocial.o
PARSING = parsing
MAP_TEST = map_example_test
ISOCIAL_TEST = Isocial_test
NETWORK_TEST = network_test
USER_TEST = user_test
TEST_PATH = ./tests/
$(PARSING) : $(PARSING_OBJS)
$(CC) $(DEBUG_FLAG) $(PARSING_OBJS) $(LIB) -o $#
$(MAP_TEST) : $(MAP_OBJS)
$(CC) $(DEBUG_FLAG) $(MAP_OBJS) $(LIB) -o $#
$(ISOCIAL_TEST) : $(ISOCIAL_OBJS)
$(CC) $(DEBUG_FLAG) $(ISOCIAL_OBJS) $(LIB) -o $#
$(USER_TEST) : &(USER_OBJS)
$(CC) $(DEBUG_FLAG) $(USER_OBJS) $(LIB) -o $#
$(NETWORK_TEST) : $(NETWORK_OBJS)
$(CC) $(DEBUG_FLAG) $(MAP_OBJS) $(LIB) -o $#
map.o: map.c map.h mtm_ex2.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
isocial.o: Isocial.c user.h mtm_ex2.h set.h network.h list.h Isocial.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
parsing.o: parsing.c Isocial.h parsing.h mtm_ex2.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
network.o: network.c network.h set.h mtm_ex2.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
user.o:user.c user.h set.h mtm_ex2.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
user_test.o: user_test.c ../test_utilities.h ../user.h ../mtm_ex2.h \
../set.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $(TEST_PATH)$*.c
Isocial_test.o: Isocial_test.c ../test_utilities.h ../Isocial.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c $(TEST_PATH)$*.c
map_example_test.o: map_example_test.c ../test_utilities.h ../map.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c $(TEST_PATH)$*.c
network_test.o: network_test.c ../test_utilities.h ../network.h ../set.h \
../mtm_ex2.h
$(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c $(TEST_PATH)$*.c
EXEC = $(PARSING) $(MAP_TEST) $(ISOCIAL_TEST $(USER_TEST) $(NETWORK_TEST)
tests : $(MAP_TEST) $(ISOCIAL_TEST) $(USER_TEST) $(NETWORK_TEST)
isocial : $(PARSING)
clean:
rm -f $(PARSING_OBJS) $(EXEC)
The error message is correct: I see a target for map.o, but there's no target for map, which would look like
map: map.o
something something something
There are targets for programs named parsing, map_example_test, network_test, and Isocial_test; perhaps you want to build one of those?
If you just typed make, it would build the program parsing, as that's the first target in the file.