Make file:
INCLUDE = -I/usr/X11R6/include/
LIBDIR = -L/usr/X11R6/lib
COMPILERFLAGS = -Wall
CC = g++
CFLAGS = $(COMPILERFLAGS) $(INCLUDE)
LIBRARIES = -lX11 -lXi -lXmu -lglut -lGL -lGLU -lm
All: project
project: main.o landscape.o point.o
$(CC) $(CFLAGS) -o $# $(LIBDIR) $< $(LIBRARIES)
clean:
rm *.o
I have a landscape.cpp, landscape.h, point.cpp, point.h, and main.cpp files
I'm including "point.h" in my main.cpp file and i'm getting:
g++ -Wall -I/usr/X11R6/include/ -o project -L/usr/X11R6/lib main.cpp -lX11 -lXi -lXmu -lglut -lGL -lGLU -lm
/tmp/ccdpJ8HH.o: In function main':
main.cpp:(.text+0x1c0): undefined reference toPoint::Point(int, int)'
collect2: error: ld returned 1 exit status
Makefile:15: recipe for target 'project' failed
make: *** [project] Error 1
project: main.o landscape.o point.o
$(CC) $(CFLAGS) -o $# $(LIBDIR) $< $(LIBRARIES)
Here you need to link all .o files. The rule you have here will only use the main.o file. Because $<is the first dependency only. $^ should be for all three. So try:
project: main.o landscape.o point.o
$(CC) $(CFLAGS) -o $# $(LIBDIR) $^ $(LIBRARIES)
I suggest you to use a more complete Makefile.
Also, use CXX=g++ and CXXFLAGS instead of CC and CFLAGS, because you are compiling C++ and make have special variables.
Here is an example of Makefile I could use.
# Project name
NAME= project
# Include directory
INC_DIR= /usr/X11R6/include/
# Library directory
LIB_DIR= /usr/X11R6/lib/
# Compiler
CXX= g++
# Source files
SRC_DIR= # in case your cpp files are in a folder like src/
SRC_FILES= main.c \
landscape.c \
point.c
# Obj files
OBJ= $($(addprefix $(SRC_DIR), $(SRC_FILES)):.c=.o)
# that rule is composed of two steps
# addprefix, which add the content of SRC_DIR in front of every
# word of SRC_FILES
# And a second rule which change every ".c" extension into ".o"
LIBS= X11 \
Xi \
Xmu \
glut \
GL \
GLU \
m
# Compilation flags
CXXFLAGS= -Wall
CXXFLAGS+= $(addprefix -I, $(INC_DIR))
LDFLAGS= $(addprefix -L, $(LIB_DIR)) \
$(addprefix -l, $(LIBS))
# Rules
# this rule is only linking, no CFLAGS required
$(NAME): $(OBJ) # this force the Makefile to create the .o files
$(CXX) -o $(NAME) $(OBJ) $(LDFLAGS)
All: $(NAME)
# Remove all obj files
clean:
rm -f $(OBJ)
# Remove all obj files and the binary
fclean: clean
rm -f $(NAME)
# Remove all and recompile
re: fclean all
# Rule to compile every .c file into .o
%.o: %.c
$(CXX) -o $# -c $< $(CFLAGS)
# Describe all the rules who do not directly create a file
.PHONY: All clean fclean re
I'm not sure it's perfect, but it's better.
Also don't forget to put you project rule before your All rule to avoid relinking when simply calling make.
That way, you can also add beautiful messages (in the %.o: %.c rule for example).
With that you just have to do make re to get your binary fully updated.
Related
I'm programming on Xcode. I include SDL_image.h as
#include <SDL2/SDL_image.h>
and it says 'SDL2/SDL_image.h' file not found
I have installed and linked binary with libraries both SDL2.framework and SDL2_image.framework.
I used a Makefile to compile and there is an error: fatal error: 'SDL2/SDL_image.h' file not found
Here is my Makefile
# set the compiler
CC := clang
# set the compiler flags
CXXFLAGS = -std=c++14 -Wall -MMD -Werror=vla pkg-config --cflags --libs sdl2 `-L/Library/Frameworks/ sdl2-config --libs --cflags` -ggdb3 -O0 --std=c99 -Wall -l SDL2_image -lm
# add source files here
SRCS := main.cpp #file-name.c
# generate names of object files
OBJS := $(SRCS:.c=.o)
# name of executable
EXEC := sdl #name your executable file
# default recipe
all: $(EXEC)
showfont: showfont.c Makefile
$(CC) -o $# $#.c $(CFLAGS) $(LIBS)
glfont: glfont.c Makefile
$(CC) -o $# $#.c $(CFLAGS) $(LIBS)
# recipe for building the final executable
$(EXEC): $(OBJS) $(HDRS) Makefile
$(CC) -o $# $(OBJS) $(CFLAGS)
# recipe for building object files
#$(OBJS): $(#:.o=.c) $(HDRS) Makefile
# $(CC) -o $# $(#:.o=.c) -c $(CFLAGS)
# recipe to clean the workspace
clean:
rm -f $(EXEC) $(OBJS)
.PHONY: all clean
I'm having a little trouble adapting a makefile I found here. What I have is below. When I run it, I get hundreds of "undefined reference to" errors, mostly complaining about the inability to find things in UnitTest. For example, the first is
/home/t/pf/test/main.cpp:63: undefined reference to `UnitTest::RunAllTests()'
Why is this happening? Does this have something to do with how the dependencies are being automatically generated?
Here's the makefile:
# output binary
BIN := main
# source files
SRCS := \
main.cpp test_resamplers.cpp test_rv_eval.cpp test_rv_samp.cpp
# intermediate directory for generated object files
OBJDIR := .o
# intermediate directory for generated dependency files
DEPDIR := .d
# object files, auto generated from source files
OBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(SRCS)))
# compilers (at least gcc and clang) don't create the subdirectories automatically
$(shell mkdir -p $(DEPDIR))
$(shell mkdir -p $(dir $(OBJS)) >/dev/null)
# C++ compiler
CXX := g++
# linker
LD := g++
# C++ flags
CXXFLAGS := -std=c++11
# C/C++ flags
CPPFLAGS := -g -Wall -Wextra -pedantic -I/usr/local/include/UnitTest++ -I/usr/include/eigen3 -I../include
# linker flags
LDFLAGS := "-L../bin" "-L/usr/local/lib"
# flags required for dependency generation; passed to compilers
DEPFLAGS = -MT $# -MD -MP -MF $(DEPDIR)/$*.Td
# libraries
LDLIBS := -lpf -lUnitTest++
# compile C++ source files
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -o $#
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) $(LDLIBS) -o $#
# precompile step
PRECOMPILE =
# postcompile step
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
all: $(BIN)
.PHONY: clean
clean:
$(RM) -r $(OBJDIR) $(DEPDIR)
.PHONY: help
help:
#echo available targets: all clean
$(BIN): $(OBJS)
$(LINK.o) $^
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
.PRECIOUS = $(DEPDIR)/%.d
$(DEPDIR)/%.d: ;
-include $(DEPS)
All your undefined references must appear when line $(LINK.o) $^ is reached, this message is a link problem.
with g++ the link order matters see link order. I would try replacing
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) $(LDLIBS) -o $#
by
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) -o $#
and
$(BIN): $(OBJS)
$(LINK.o) $^
by
$(BIN): $(OBJS)
$(LINK.o) $^ $(LDLIBS)
I want my object files to be created in a subdirectory and not where Makefile lives. So, I saw this answer, which I couldn't apply to my case, so I tried this:
OBJS = main.o IO.o alloc.o communication.o
OBJSDIR = obj
SOURCE = main.cpp src/IO.cpp src/alloc.cpp src/communication.cpp
HEADER = headers/IO.h headers/alloc.h headers/communication.h
OUT = test
CXX = ../../mpich-install/bin/mpic++
CXXFLAGS = -I../../intel/mkl/include -Wl,--start-group -Wl,--end-group -lpthread -lm -ldl -Wall
LDFLAGS = ../../intel/mkl/lib/intel64/libmkl_scalapack_lp64.a -Wl,--start-group ../../intel/mkl/lib/intel64/libmkl_intel_lp64.a ../../intel/mkl/lib/intel64/libmkl_core.a ../../intel/mkl/lib/intel64/libmkl_sequential.a -Wl,--end-group ../../intel/mkl/lib/intel64/libmkl_blacs_intelmpi_lp64.a -lpthread -lm -ldl
all: $(OBJSDIR) $(OUT)
$(OBJSDIR):
mkdir $(OBJSDIR)
$(OUT): $(OBJS)
$(CXX) $(OBJS) -o $(OUT) $(CXXFLAGS) $(LDFLAGS)
# make -f Makefile clean
# create/compile the individual files >>separately<<
$(OBJSDIR)/main.o: main.cpp
$(CXX) -c main.cpp $(CXXFLAGS)
$(OBJSDIR)/IO.o: src/IO.cpp
$(CXX) -c src/IO.cpp $(CXXFLAGS)
$(OBJSDIR)/alloc.o: src/alloc.cpp
$(CXX) -c src/alloc.cpp $(CXXFLAGS)
$(OBJSDIR)/communication.o: src/communication.cpp
$(CXX) -c src/communication.cpp $(CXXFLAGS)
.PHONY: clean
clean:
rm -rf *.o
and I am getting:
gsamaras#pythagoras:~/konstantis/cholesky$ make
../../mpich-install/bin/mpic++ -I../../intel/mkl/include -Wl,--start-group -Wl,--end-group -lpthread -lm -ldl -Wall -c -o main.o main.cpp
make: *** No rule to make target 'IO.o', needed by 'test'. Stop.
I have a src folder, where all the .cpp files live (except from main.cpp, that lives in the same directory as the Makefile) and a headers directory, where all the header files live.
EDIT
I modified the first two lines, as such:
OBJSDIR = obj
OBJS = $(OBJSDIR)/main.o $(OBJSDIR)/IO.o $(OBJSDIR)/alloc.o $(OBJSDIR)/communication.o
and I am getting:
g++: error: obj/main.o: No such file or directory
...
The problem lies into the fact that the object files are still generated in the main directory!
You want to change the lines that invoke your compiler from:
$(OBJSDIR)/IO.o: src/IO.cpp
$(CXX) -c src/IO.cpp $(CXXFLAGS)
to:
$(OBJSDIR)/IO.o: src/IO.cpp
$(CXX) -c src/IO.cpp $(CXXFLAGS) -o $#
Note that $# is the automatic variable that corresponds to the target file being created. So in the above case it will be obj/IO.o. -o specifies the output filename.
Furthermore while it is unrelated to your question one of the nice things about placing all the build artifacts into a separate directory is cleaning is much easier:
clean:
rm -rf $(OBJSDIR) $(OUT)
Also, as a final note if you ever wish to do a parallel build you will have an issue as your object files rely on the build directory. There are a couple solutions to this including calling mkdir -p objs before every compiler invocation or setting up the directory as a dependency that is only built if it does not exist.
I have been asked to port our product into another application.(our s/w is running on linux virtualbox)
I have got a directory of their interface files and also a example code on trying to configure their software/hardware. I see their interface files under the s/w directory. In the reference code directory, I see a makefile with the reference to their reference code.
Trying to run their reference code makefile. getting error that
make: *** No rule to make target `../ main.o" :(
Btw donot understand why SIMUDIR = -I\..\custom_simcode\ this is done in the makefile ?
Also not much familiar with crosscompiler syntax !
ifndef CROSS_CC_PREFIX
CROSS_CC_PREFIX=$(CROSS_COMPILE)
endif
PROGRAM = customer_sim
CC=$(CROSS_CC_PREFIX)gcc
LD=$(CROSS_CC_PREFIX)ld
RANLIB=$(CROSS_CC_PREFIX)corelib
CFLAGS= -g
all: $(PROGRAM)
## Include path
SIMUDIR = -I\..\custom_simcode\
CUST_INT_INC = -I./../cust_Intf/DecHandler/inc \
-I./../CCPU
LIBDIR = -L./../cust_Intf \
-L./../cust_IntfApi
LIBS = -lpthread -customercif -customerapi
LDFLAGS= $(LIBDIR) $(LIBS)
SOURCE = ./../custom_simcode/main.c \
./../custom_simcode/custcode_primitives_init.c \
./../custom_simcode/custccp_primitives_init.c
CFLAGS += $(SIMUDIR) $(CUST_INT_INC) -DPRINT_IO_CONSOLE -UADAPT_CCPU_CUSTIF
OBJS = $(SOURCE:.c=.o)
$(PROGRAM): $(OBJS)
$(CC) -o $# $(OBJS) $(LDFLAGS)
main.o: $(SIMUDIR)/main.c $(SIMUDIR) $(CUST_INT_INC)
$(CC) -c -o /main.o $(SIMUDIR)/main.c
clean:
-rm -f $(OBJS) $(OBJS) $(PROGRAM)
Your $(OBJS) list dependencies for $(PROGRAMs) with directories included but your rule for main.o doesn't have same path.
It would be better to have a generic rule to compile C files like
%.o: %.c
$(CC) -c -o $# $<
Then simply assign extra dependencies for each file like:
$(OBJS): $(SIMUDIR) $(CUST_INT_INC)
(On Linux, trying to set up SDL) I'm having a time with makefiles, I'm finding them hard to learn. Here is the error I'm getting.
g++: error: game.exe: No such file or directory
make: *** [game.exe] Error 1
Here is my makefile. (Any suggestions on making it better would be great. I've just kind of slapped together whatever I could find to work.)
#Game Make file
TARGET = game.exe
OBJS = App.o\
App_OnInit.o\
App_OnEvent.o\
App_OnLoop.o\
App_OnRender.o \
App_OnCleanup.o\
SDL_CFLAGS := $(shell sdl-config --cflags)
SDL_LDFLAGS := $(shell sdl-config --libs)
CFLAGS = -Wall -o
LIBS =
LDFLAGS =
$(TARGET): $(OBJS)
g++ $(CFLAGS) $(SDL_CFLAGS) $# $(LDFLAGS) $(OBJS) $(SDL_LDFLAGS) $(LIBS)
%.o: src/%.cpp
g++ -c $(SDL_CFLAGS) $< $(SDL_LDFLAGS)
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJS)
You could either exchange $(CFLAGS) and $(SDL_CFLAGS) in the rule to make $(TARGET) or better remove -o from CFLAGS and put it directly before $#:
...
CFLAGS = -Wall
...
$(TARGET): $(OBJS)
g++ $(CFLAGS) $(SDL_CFLAGS) -o $# $(LDFLAGS) $(OBJS) $(SDL_LDFLAGS) $(LIBS)
-o option should immediately precede the name of the executable file to be produced. In your original Makefile it is part of $(CFLAGS) and is followed by the C flags of the SDL library. Therefore the compiler tries to link in game.exe (the $#) instead of producing an executable file by that name.