Function multiple definition linker error building on GCC - Makefile issue

≡放荡痞女 提交于 2019-12-08 02:34:07

问题


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?


回答1:


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.




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/11940191/function-multiple-definition-linker-error-building-on-gcc-makefile-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!