Makefile似乎是以错误的顺序编译文件

时间:2017-04-24 09:32:05

标签: c++ makefile g++ gnu-make

我自己创建了一个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中究竟搞砸了什么,它是否一般都有好处,或者除了立即编译问题之外还有其他任何缺陷吗?

1 个答案:

答案 0 :(得分:1)

从纯粹的技术角度来看,.o的行是错误的,因为它有:

.cpp.o:
    $(LD) $(CFLAGS) $< -o $@

这将导致生成一个已链接的文件;因此,在.o文件中会注入一堆额外的值,这在链接步骤中是不可取的:

$(EXECUTABLE): $(OBJECTS)
    $(LD) $(LDFLAGS) $(OBJECTS) -o $@

因此,让我们按顺序获取makefile的术语 - 编译使用CC++编译器,这通常涉及使用变量CCCXX ,所以我们只是将.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中编写的代码量