问题
I'm trying to make a makefile for a multi-file C++ project that builds object files, then builds my application from those object files.
It works without any errors when I use the command:
all: src/main.cpp src/main_funcs.cpp src/menu.cpp src/logging.cpp\
src/runonce.cpp src/wordify.cpp src/vte.cpp
g++ -Wall `pkg-config --cflags gtk+-3.0, vte-2.91, glib-2.0, gio-2.0`\
-std=c++14 -o "updater" src/main.cpp src/main_funcs.cpp \
src/logging.cpp src/menu.cpp src/runonce.cpp \
src/wordify.cpp src/vte.cpp `pkg-config \
--libs gtk+-3.0, vte-2.91, glib-2.0, gio-2.0` -lboost_date_time \
-lboost_system -lpthread
But when I attempt to use my other makefile, I get a litany of linker errors (multiple definitions, undefined references). The relevant parts of the other makefile are:
IDIR = include
ODIR = obj
SRC_DIR = src
CXX = g++
CXXFLAGS = -Wall -std=c++14 \
`pkg-config --cflags gtk+-3.0, vte-2.91, glib-2.0, gio-2.0`
LIBS = `pkg-config --libs gtk+-3.0, vte-2.91, glib-2.0, gio-2.0` \
-lboost_date_time -lboost_system -lpthread
_FILES = main.cpp main_funcs.cpp menu.cpp logging.cpp wordify.cpp \
runonce.cpp vte.cpp
FILES = $(patsubst %,$(SRC_DIR)/%,$(_FILES))
_DEPS = include.h logging.h main_funcs.h main_gtk.h menu.h runonce.h \
vte_include.h wordify.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o main_funcs.o menu.o logging.o wordify.o runonce.o vte.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
VPATH = $(ODIR):$(IDIR)
OUT = -o $(BDIR)/update
$(ODIR)/%.o: $(FILES) $(DEPS)
$(CXX) $(CXXFLAGS) -c -o $@ $< $(LIBS)
all: $(OBJ)
$(CXX) $(CXXFLAGS) $(OUT) $^ $(LIBS)
I've tried possible solutions from similar threads. No dice. Any help would be great. I can post more stuff if I need to.
Here's the linker error:
obj/main_funcs.o:(.bss+0x0): multiple definition of `rank_run_count'
obj/main.o:(.bss+0x0): first defined here
obj/main_funcs.o:(.bss+0x4): multiple definition of `update_run_count'
obj/main.o:(.bss+0x4): first defined here
obj/main_funcs.o: In function `notroot(_GtkWidget*)':
main.cpp:(.text+0x0): multiple definition of `notroot(_GtkWidget*)'
obj/main.o:main.cpp:(.text+0x0): first defined here
obj/main_funcs.o: In function `main':
main.cpp:(.text+0x4f1): multiple definition of `main'
obj/main.o:main.cpp:(.text+0x4f1): first defined here
obj/menu.o:(.bss+0x0): multiple definition of `rank_run_count'
obj/main.o:(.bss+0x0): first defined here
obj/menu.o:(.bss+0x4): multiple definition of `update_run_count'
obj/main.o:(.bss+0x4): first defined here
obj/menu.o: In function `notroot(_GtkWidget*)':
main.cpp:(.text+0x0): multiple definition of `notroot(_GtkWidget*)'
obj/main.o:main.cpp:(.text+0x0): first defined here
obj/menu.o: In function `main':
main.cpp:(.text+0x4f1): multiple definition of `main'
obj/main.o:main.cpp:(.text+0x4f1): first defined here
obj/logging.o:(.bss+0x0): multiple definition of `rank_run_count'
obj/main.o:(.bss+0x0): first defined here
obj/logging.o:(.bss+0x4): multiple definition of `update_run_count'
obj/main.o:(.bss+0x4): first defined here
obj/logging.o: In function `notroot(_GtkWidget*)':
main.cpp:(.text+0x0): multiple definition of `notroot(_GtkWidget*)'
obj/main.o:main.cpp:(.text+0x0): first defined here
obj/logging.o: In function `main':
main.cpp:(.text+0x4f1): multiple definition of `main'
obj/main.o:main.cpp:(.text+0x4f1): first defined here
obj/wordify.o:(.bss+0x0): multiple definition of `rank_run_count'
obj/main.o:(.bss+0x0): first defined here
obj/wordify.o:(.bss+0x4): multiple definition of `update_run_count'
obj/main.o:(.bss+0x4): first defined here
obj/wordify.o: In function `notroot(_GtkWidget*)':
main.cpp:(.text+0x0): multiple definition of `notroot(_GtkWidget*)'
obj/main.o:main.cpp:(.text+0x0): first defined here
obj/wordify.o: In function `main':
main.cpp:(.text+0x4f1): multiple definition of `main'
obj/main.o:main.cpp:(.text+0x4f1): first defined here
obj/runonce.o:(.bss+0x0): multiple definition of `rank_run_count'
obj/main.o:(.bss+0x0): first defined here
obj/runonce.o:(.bss+0x4): multiple definition of `update_run_count'
obj/main.o:(.bss+0x4): first defined here
obj/runonce.o: In function `notroot(_GtkWidget*)':
main.cpp:(.text+0x0): multiple definition of `notroot(_GtkWidget*)'
obj/main.o:main.cpp:(.text+0x0): first defined here
obj/runonce.o: In function `main':
main.cpp:(.text+0x4f1): multiple definition of `main'
obj/main.o:main.cpp:(.text+0x4f1): first defined here
obj/vte.o:(.bss+0x0): multiple definition of `rank_run_count'
obj/main.o:(.bss+0x0): first defined here
obj/vte.o:(.bss+0x4): multiple definition of `update_run_count'
obj/main.o:(.bss+0x4): first defined here
obj/vte.o: In function `notroot(_GtkWidget*)':
main.cpp:(.text+0x0): multiple definition of `notroot(_GtkWidget*)'
obj/main.o:main.cpp:(.text+0x0): first defined here
obj/vte.o: In function `main':
main.cpp:(.text+0x4f1): multiple definition of `main'
obj/main.o:main.cpp:(.text+0x4f1): first defined here
obj/main.o: In function `mainwin(_GtkApplication*, void*)':
main.cpp:(.text+0x219): undefined reference to `main_menu_render()'
main.cpp:(.text+0x29d): undefined reference to `rank_callback(_GtkWidget*, void*, _GtkWidget*)'
main.cpp:(.text+0x2d4): undefined reference to `update_callback(_GtkWidget*, void*, _GtkWidget*)'
obj/main_funcs.o: In function `mainwin(_GtkApplication*, void*)':
main.cpp:(.text+0x219): undefined reference to `main_menu_render()'
main.cpp:(.text+0x29d): undefined reference to `rank_callback(_GtkWidget*, void*, _GtkWidget*)'
main.cpp:(.text+0x2d4): undefined reference to `update_callback(_GtkWidget*, void*, _GtkWidget*)'
obj/menu.o: In function `mainwin(_GtkApplication*, void*)':
main.cpp:(.text+0x219): undefined reference to `main_menu_render()'
main.cpp:(.text+0x29d): undefined reference to `rank_callback(_GtkWidget*, void*, _GtkWidget*)'
main.cpp:(.text+0x2d4): undefined reference to `update_callback(_GtkWidget*, void*, _GtkWidget*)'
obj/logging.o: In function `mainwin(_GtkApplication*, void*)':
main.cpp:(.text+0x219): undefined reference to `main_menu_render()'
main.cpp:(.text+0x29d): undefined reference to `rank_callback(_GtkWidget*, void*, _GtkWidget*)'
main.cpp:(.text+0x2d4): undefined reference to `update_callback(_GtkWidget*, void*, _GtkWidget*)'
obj/wordify.o: In function `mainwin(_GtkApplication*, void*)':
main.cpp:(.text+0x219): undefined reference to `main_menu_render()'
main.cpp:(.text+0x29d): undefined reference to `rank_callback(_GtkWidget*, void*, _GtkWidget*)'
main.cpp:(.text+0x2d4): undefined reference to `update_callback(_GtkWidget*, void*, _GtkWidget*)'
obj/runonce.o: In function `mainwin(_GtkApplication*, void*)':
main.cpp:(.text+0x219): undefined reference to `main_menu_render()'
main.cpp:(.text+0x29d): undefined reference to `rank_callback(_GtkWidget*, void*, _GtkWidget*)'
main.cpp:(.text+0x2d4): undefined reference to `update_callback(_GtkWidget*, void*, _GtkWidget*)'
obj/vte.o: In function `mainwin(_GtkApplication*, void*)':
main.cpp:(.text+0x219): undefined reference to `main_menu_render()'
main.cpp:(.text+0x29d): undefined reference to `rank_callback(_GtkWidget*, void*, _GtkWidget*)'
main.cpp:(.text+0x2d4): undefined reference to `update_callback(_GtkWidget*, void*, _GtkWidget*)'
collect2: error: ld returned 1 exit status
Makefile:41: recipe for target 'all' failed
make: *** [all] Error 1
回答1:
Your $(ODIR)/%.o: $(FILES) $(DEPS)
rule is wildly wrong.
You are telling make that every output .o
file depends on every .cpp
and .h
file.
Additionally, the rule for that target is only ever using $<
which is the first prerequisite which is the first entry in $(FILES)
.
So every single one of your output .o
files is simply main.cpp
compiled.
You should drop the recipe in that rule entirely and let make use its built-in %.o: %.cpp
rule. (You'll need to update your VPATH
stuff to tell make how to find your source files to do that though.)
Alternatively, you need to use an actual pattern rule there $(OUT)/%.o: $(SRC)/%.cpp
, etc.
There are other inefficiencies in the makefile (not least of which is that you are having make run pkg-config
multiple times, once each time it needs to expand $(CXXFLAGS)
and $(LIBS)
). But those are a bit farther out of scope.
来源:https://stackoverflow.com/questions/31550368/c-linker-error-when-trying-to-build-from-object-files-made-using-makefile-doe