我自己创建了一个makefile作为测试各种功能的教程。似乎我有一个错误,因为它给了我输出:
g++ src/test1.o -o dcpu-16
src/test1.o: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.fini+0x0): first defined here
src/test1.o: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.data+0x0): first defined here
src/test1.o: In function `data_start':
(.data+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o:(.data+0x0): first defined here
src/test1.o:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.rodata.cst4+0x0): first defined here
src/test1.o: In function `_start':
(.text+0x10): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here
src/test1.o: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.init+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
src/test1.o:(.data+0x10): first defined here
/usr/bin/ld: error in src/test1.o(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
makefile:35: recipe for target 'dcpu-16' failed
make: *** [dcpu-16] Error 1
使用的makefile是:
WARNINGS := -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align \
-Wwrite-strings -Wmissing-prototypes -Wmissing-declarations \
-Wredundant-decls -Wnested-externs -Winline -Wno-long-long \
-Wuninitialized -Wconversion -Wstrict-prototypes -Wno-unused-function
CC := gcc
CXX := g++
LD := g++
CP := cp
SOURCES:=$(shell find src/ -name "*.cpp")
OBJECTS=$(SOURCES:.cpp=.o)
DEPFILES := $(OBJECTS:.o=.d)
GARBAGE := core core.* *.stackdump ./tags $(EXECUTABLE)
EXECUTABLE=dcpu-16
OPTFLAGS := -g -O3
CFLAGS += $(OPTFLAGS) $(WARNINGS)
CXXFLAGS += $(CFLAGS)
LDFLAGS=
ifeq ($(DEBUG_BUILD),1)
CFLAGS +=-DDEBUG_BUILD
endif
.PHONY: clean all
default: $(EXECUTABLE)
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(LD) $(LDFLAGS) $(OBJECTS) -o $@
.cpp.o:
$(LD) $(CFLAGS) -c $< -o $@
clean:
rm -rf $(EXECUTABLE) $(OBJECTS) $(GARBAGE) $(DEPFILES)
我在上面的makefile中究竟搞砸了什么,它是否一般都有好处,或者除了立即编译问题之外还有其他任何缺陷吗?
答案 0 :(得分:1)
从纯粹的技术角度来看,.o
的行是错误的,因为它有:
.cpp.o:
$(LD) $(CFLAGS) $< -o $@
这将导致生成一个已链接的文件;因此,在.o
文件中会注入一堆额外的值,这在链接步骤中是不可取的:
$(EXECUTABLE): $(OBJECTS)
$(LD) $(LDFLAGS) $(OBJECTS) -o $@
因此,让我们按顺序获取makefile的术语 - 编译使用C
或C++
编译器,这通常涉及使用变量CC
或CXX
,所以我们只是将.cpp
文件编译成.o
文件,所以我们应该使用C ++编译器和C ++标志进行编译:
.cpp.o:
$(CXX) $(CXXFLAGS) $< -o $@
对Makefile
进行更改不会导致已构建的文件突然变为无效(除非我们使所有文件都依赖于Makefile),因此您需要清理已经编译的文件 - 您会有一个.o
文件被错误地构建,make clean
的调用会删除这个.o
文件,以便随后调用make会重建它。
至于Makefile
的一些风格项目;你通常会这样做:
CFLAGS
== C编译器的标志仅 CXXFLAGS
== C ++编译器的标志仅 CPPFLAGS
== C预处理器的标志仅 您可以使用make -p
转储make的默认数据库,这表示它是各种文件类型的默认编译和链接行,并显示:
.cpp.o:
# Builtin rule
# Implicit rule search has not been done.
# Modification time never checked.
# File has not been updated.
# recipe to execute (built-in):
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
COMPILE.cpp = $(COMPILE.cc)
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
您可以构建这些内置规则,以减少需要在makefile中编写的代码量