首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Makefile似乎在按错误的顺序编译文件。

Makefile似乎在按错误的顺序编译文件。
EN

Stack Overflow用户
提问于 2017-04-24 09:32:05
回答 1查看 848关注 0票数 0

我自己创建了一个makefile,作为测试各种特性的教程。但是,似乎我有一个错误,因为它给出了输出:

代码语言:javascript
复制
    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如下:

代码语言:javascript
复制
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上搞错了什么?总的来说,它是有什么好处的,还是除了直接编译问题之外,还有其他的缺陷呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-24 10:35:50

从纯粹的技术角度来看,使.o生成的这条线是错误的,因为它有:

代码语言:javascript
复制
.cpp.o:
    $(LD) $(CFLAGS) $< -o $@

这将导致生成已链接的文件;因此,将向.o文件注入一组额外的值,当涉及到链接步骤时,这些值是不被期望的:

代码语言:javascript
复制
$(EXECUTABLE): $(OBJECTS)
    $(LD) $(LDFLAGS) $(OBJECTS) -o $@

因此,让我们按照顺序获得makefile的术语--编译使用CC++编译器,这通常涉及使用变量CCCXX,所以我们只是将.cpp文件编译成.o文件,所以应该使用C++编译器和C++标志进行编译:

代码语言:javascript
复制
.cpp.o:
    $(CXX) $(CXXFLAGS) $< -o $@

Makefile的更改不会导致已经生成的文件突然失效(除非我们使所有文件都依赖于Makefile),所以您需要清理已经编译的文件--您可能有一个构建错误的.o文件,对make clean的调用将删除这个.o文件,以便后续调用make将重新构建它。

至于Makefile的一些文体项目,您通常这样做:

  • 仅用于C编译器的CFLAGS ==标志
  • 仅用于CXXFLAGS编译器的==标志
  • 仅用于C预处理器的CPPFLAGS ==标志

您可以使用make -p将make的默认数据库转储出来,这将指示它针对各种文件类型的默认编译和链接行,它显示:

代码语言:javascript
复制
.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中编写的代码数量。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43584507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档