所以我试图使用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一样似乎工作,所以我不知道是什么问题。任何人都有任何想法?如有必要,我可以提供更多信息吗?
答案 0 :(得分:7)
我在头文件中声明了+定义了一些函数,并将其定义移动到cpp中,从链接器错误中删除了这些函数
听起来它们不是内联的,在这种情况下,只有在链接程序时才允许使用单个定义。
将inline
添加到标头中的任何函数定义以解决问题。这放宽了“一个定义规则”,允许在多个翻译单元中定义这些功能,只要所有定义都相同。
更新:此外,您对OBJS_SPLOTCH_DEFAULT
的定义包含重复项;重复cxxsupport/paramfile.o
,可能还有其他人。您需要删除重复项。我建议按字母顺序保留这样的长列表,以便更容易搜索和查找重复项。
答案 1 :(得分:1)
问题不在makefile中。就在这里:
我在标题中声明了+定义了一些函数,然后移动了它们 cpp中的定义从链接器错误中删除了那些函数 - 但是我不能为所有人做这件事,因为很大一部分是我无法编辑的代码库。
问题在于,当您在多个源文件中包含该标头时,您将获得多个函数定义副本,这就是链接器所抱怨的内容。所以你有三个选择:不要使用那些代码(严重的:一般来说,这是一个可怕的编码实践);不要在多个源文件中使用该标头;或者像@Mike建议的那样添加内联。
答案 2 :(得分:1)
如果您在.h
文件中定义并声明了一个函数,那么除非您可以通过编译选项或使用{{1}来减少变量的范围,否则您将获得多个定义的符号。 }。
如果你不能重写这些inline
文件来将例程声明为.h
,那么一个丑陋的解决方案就是创建一个并行inline
,只需重新声明所有这些例程(声明,介意,也没有定义)。您的所有代码.h
此并行#includes
文件。
您创建了一个.h
/ .c
个文件,其中.cpp
来自共享代码库的#includes
个文件。
您链接生成的单个.h
,它将来自共享代码库的实现公开到您的代码库中。
这很难看,而且是黑客,我肯定是使用@ Mike的答案而不是这个答案。