簡體   English   中英

在GCC上構建函數多定義鏈接器錯誤 - Makefile問題

[英]Function multiple definition linker error building on GCC - Makefile issue

所以我試圖使用Makefile來構建一個項目,而且我對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一樣似乎工作,所以我不知道是什么問題。 任何人都有任何想法? 如有必要,我可以提供更多信息嗎?

我在頭文件中聲明了+定義了一些函數,並將它們的定義移動到cpp中,從鏈接器錯誤中刪除了這些函數

聽起來它們不是內聯的,在這種情況下,在鏈接程序時只允許單個定義。

inline添加到標頭中的任何函數定義以解決問題。 這放寬了“一個定義規則”以允許在多個翻譯單元中定義這些功能,只要所有定義相同即可。

更新:此外,您對OBJS_SPLOTCH_DEFAULT的定義包含重復項; 重復cxxsupport/paramfile.o ,可能還有其他人。 您需要刪除重復項。 我建議按字母順序保留這樣的長列表,以便更容易搜索和查找重復項。

問題不在makefile中。 它在這里:

我在頭文件中聲明了+定義了一些函數,並將它們的定義移動到cpp中,從鏈接器錯誤中刪除了這些函數 - 但我不能對所有這些函數執行此操作,因為很大一部分是我無法編輯的代碼庫。

問題是,當您在多個源文件中包含該標頭時,您將獲得多個函數定義副本,這就是鏈接器所抱怨的內容。 所以你有三個選擇:不要使用那些代碼(嚴重的:一般來說,這是一個可怕的編碼實踐); 不要在多個源文件中使用該標頭; 或者像@Mike建議的那樣添加內聯。

如果您在.h文件中定義並聲明了一個函數,那么除非您可以通過編譯選項或使用inline來減少變量的范圍,否則您將獲得多個定義的符號。

如果你不能重寫這些.h文件來將例程聲明為inline ,那么一個丑陋的解決方案是創建一個並行的.h ,它只是重新聲明所有這些例程(聲明,介意,也沒有定義)。 你所有的代碼#includes此平行.h文件。

您創建一個.c / .cpp文件,其中#includes來自共享代碼庫的.h文件。

您鏈接生成的單個.o ,它將來自共享代碼庫的實現公開到您的代碼庫中。

這是丑陋的,而且是黑客,我肯定會使用@ Mike的答案而不是這個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM