C++ linker error when trying to build from object files made using makefile. Does not occur when I just build it

∥☆過路亽.° 提交于 2019-12-11 10:06:07

问题


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

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