Reputation: 620
So I am trying to use a Makefile to build a project, and im relatively new to makefiles in general. I am getting multiple definition errors when linking for loads of functions, and im pretty sure it is due to my makefile. I cannot post much of the project, as it is pretty large, but the makefile is below, does anything stand out as obviously wrong?
I had some functions declared + defined in a header, and moving their definitions into a cpp removed those functions from the linker errors - but I cannot do this for all of them (EDIT: The rest of the functions that are being multiply defined are not in headers, they are in cpp/cc files as standard, saying "i cannot do this for all of them" implied they were all like that, sorry), as a large portion is a codebase I cannot edit. There shouldnt be any errors in the code though as it is building fine in a separate project without my additions (none of which are causing linker errors), so I figure it must be my makefile, but I cant figure out what I am doing wrong. Any Ideas?
# Compiler
CXX = g++
# Linker settings
LDFLAGS = -lGL -lGLU -lXext -lX11
# Executable name
EXEC = SplotchPreviewer
# Optimizations for compilation
OPTIMIZE = -std=c++98 -pedantic -Wno-long-long -Wfatal-errors -Wextra -Wall -Wstrict-aliasing=2 -Wundef -Wshadow -Wwrite-strings -Wredundant-decls -Woverloaded-virtual -Wcast-qual -Wcast-align -Wpointer-arith -O2 -g
# Pre-processor settings
CPPFLAGS = $(OPTIMIZE) -I. -Icxxsupport -Ic_utils
# Default Splotch objects
OBJS_SPLOTCH_DEFAULT = cxxsupport/error_handling.o reader/mesh_reader.o cxxsupport/mpi_support.o cxxsupport/paramfile.o \
cxxsupport/string_utils.o cxxsupport/announce.o reader/gadget_reader.o reader/millenium_reader.o \
reader/bin_reader.o reader/tipsy_reader.o splotch/splotchutils.o splotch/scenemaker.o \
cxxsupport/walltimer.o c_utils/walltime_c.o booster/mesh_creator.o booster/randomizer.o \
booster/p_selector.o booster/m_rotation.o cxxsupport/paramfile.o cxxsupport/error_handling.o \
c_utils/walltime_c.o cxxsupport/string_utils.o cxxsupport/announce.o \
cxxsupport/walltimer.o
# Default Previewer objects
OBJS_PREVIEWER_DEFAULT = main.o previewer/Previewer.o previewer/libs/core/Parameter.o previewer/libs/core/ParticleSimulation.o \
previewer/libs/core/WindowManager.o previewer/libs/core/Camera.o previewer/libs/core/ParticleData.o \
previewer/libs/core/MathLib.o previewer/libs/core/FileLib.o previewer/libs/events/OnQuitApplicationEvent.o \
previewer/libs/events/OnKeyReleaseEvent.o previewer/libs/events/OnKeyPressEvent.o previewer/libs/events/OnExposedEvent.o \
previewer/libs/events/OnButtonReleaseEvent.o previewer/libs/events/OnButtonPressEvent.o previewer/libs/core/Texture.o \
previewer/libs/animation/AnimationSimulation.o
#temp force render method
RENDER_METHOD = FFSDL
# Current build specific objects
ifeq ($(RENDER_METHOD),FFSDL)
OBJS_BUILD_SPECIFIC = previewer/libs/renderers/FF_DrawList.o previewer/libs/materials/FF_ParticleMaterial.o
endif
# All objects for this build
OBJS = $(OBJS_SPLOTCH_DEFAULT) $(OBJS_PREVIEWER_DEFAULT) $(OBJS_BUILD_SPECIFIC)
# Rules (note: object files automatically removed when building)
.SUFFIXES: .o .cc .cxx .cpp
.cpp.o:
$(CXX) -c $(CPPFLAGS) -o "$@" "$<"
.cc.o:
$(CXX) -c $(CPPFLAGS) -o "$@" "$<"
.cxx.o:
$(CXX) -c $(CPPFLAGS) -o "$@" "$<"
$(EXEC): $(OBJS)
$(CXX) $(OBJS) $(LDFLAGS) -o $(EXEC)
rm $(OBJS)
clean:
rm -f $(OBJS)
rm -f $(EXEC)
Ive cut out one or two unneccesary things, hence one or two bits of it not making much sense (why have a render method option with only one method available for example) Im a bit hazy on whether I have written the rules correctly, and figure this could account for my issue? Although it looks the same as the other makefile which seems to work so Im not sure what the issue is. Anyone have any idea? I can provide more info if necessary?
Upvotes: 2
Views: 8490
Reputation: 254721
I had some functions declared + defined in a header, and moving their definitions into a cpp removed those functions from the linker errors
That sounds like they weren't inline, in which case you're only allowed a single definition when linking the program.
Add inline
to any function definitions in headers to fix the problem. This relaxes the "one definition rule" to allow these functions to be defined in multiple translation units, as long as all the definitions are identical.
UPDATE: Also, your definition of OBJS_SPLOTCH_DEFAULT
contains duplicates; cxxsupport/paramfile.o
is repeated, and there may be others. You'll need to remove the duplicates. I recommend keeping long lists like this in alphabetical order, to make it easier to search and to spot duplicates.
Upvotes: 7
Reputation: 94849
If you have a function defined and declared in a .h
file, then you're going to get multiply defined symbols unless you can reduce the scope of the variables through compile options or the use of inline
.
If you can't rewrite these .h
files to declare the routines as inline
, then an ugly solution is to create a parallel .h
that simply re-declares all these routines (declares, mind, not defines as well). All your code #includes
this parallel .h
file.
You create a single .c
/.cpp
file which #includes
the .h
files from the shared codebase.
You link the resulting single .o
which exposes the implementations that came from the shared codebase into your codebase.
This is ugly, and a hack, I'd definitely be one for using @Mike's answer rather than this one.
Upvotes: 1
Reputation: 76468
The problem isn't in the makefile. It's here:
I had some functions declared + defined in a header, and moving their definitions into a cpp removed those functions from the linker errors - but I cannot do this for all of them, as a large portion is a codebase I cannot edit.
The problem is that when you include that header in more than one source file you get more than one copy of the function definition, and that's what the linker is complaining about. So you have three choices: don't use that code (seriously: in general, that's a horrible coding practice); don't use that header in more than one source file; or add inline, as @Mike suggested.
Upvotes: 1