jordan
jordan

Reputation: 187

File linking with c++ makefile

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

Upvotes: 2

Views: 6513

Answers (2)

Ludonope
Ludonope

Reputation: 1093

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.

Upvotes: 0

Florian Zwoch
Florian Zwoch

Reputation: 7373

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)

Upvotes: 2

Related Questions