2

所以我正在尝试使用 Makefile 来构建一个项目,而且我一般来说对 makefile 来说相对较新。链接大量函数时出现多个定义错误,我很确定这是由于我的 makefile 造成的。我不能发布大部分项目,因为它非常大,但是生成文件在下面,有什么明显错误的地方吗?

我在头文件中声明了一些函数 + 定义,并将它们的定义移动到 cpp 中从链接器错误中删除了这些函数 - 但我不能为所有这些函数执行此操作(编辑:被多重定义的其余函数不是在标头中,它们作为标准位于 cpp/cc 文件中,说“我不能为所有人都这样做”暗示它们都是那样的,抱歉),因为很大一部分是我无法编辑的代码库。代码中不应该有任何错误,因为它在没有我添加的单独项目中构建良好(没有一个会导致链接器错误),所以我认为它一定是我的 makefile,但我不知道我做错了什么. 有任何想法吗?

    # 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)

我已经删掉了一两个不必要的东西,因此其中的一两个部分没有多大意义(例如,为什么只有一种方法可用的渲染方法选项)我对我是否正确编写了规则有点模糊,并且图这可以解释我的问题吗?虽然它看起来与其他似乎可以工作的 makefile 相同,但我不确定问题是什么。有人知道吗?如有必要,我可以提供更多信息吗?

4

3 回答 3

7

我在头文件中声明+定义了一些函数,并将它们的定义移动到cpp中从链接器错误中删除了这些函数

听起来它们不是内联的,在这种情况下,链接程序时只允许一个定义。

添加inline到标题中的任何函数定义以解决问题。这放宽了“一个定义规则”以允许在多个翻译单元中定义这些函数,只要所有定义都相同。

更新:另外,您对OBJS_SPLOTCH_DEFAULT包含重复项的定义;cxxsupport/paramfile.o重复了,可能还有其他的。您需要删除重复项。我建议按字母顺序保留这样的长列表,以便更容易搜索和发现重复项。

于 2012-08-13T18:34:11.380 回答
1

问题不在生成文件中。它在这里:

我在头文件中声明了一些函数 + 定义,并将它们的定义移动到 cpp 中从链接器错误中删除了这些函数 - 但我不能对所有这些函数都这样做,因为很大一部分是我无法编辑的代码库。

问题在于,当您在多个源文件中包含该标头时,您会获得多个函数定义的副本,这就是链接器所抱怨的。因此,您有三个选择:不使用该代码(说真的:总的来说,这是一种可怕的编码习惯);不要在多个源文件中使用该标头;或按照@Mike 的建议添加内联。

于 2012-08-13T18:39:03.237 回答
1

如果您在文件中定义和声明了一个函数.h,那么您将获得多重定义的符号,除非您可以通过编译选项或使用inline.

如果您不能重写这些.h文件以将例程声明为inline,那么一个丑陋的解决方案是创建一个.h简单地重新声明所有这些例程的并行(声明,记住,而不是定义)。你所有的代码#includes这个并行.h文件。

您创建一个.c/.cpp文件,其中包含来自共享代码库#includes的文件。.h

您将生成的单一.o公开来自共享代码库的实现链接到您的代码库。

这很丑陋,而且是一种黑客行为,我肯定会使用@Mike 的答案而不是这个答案。

于 2012-08-13T18:42:25.850 回答