Makefile - .o:文件无法识别:文件被截断?

时间:2016-09-11 16:07:17

标签: c++ makefile compilation dependencies gnu-make

我刚刚学习GNU make,但是在使用.d(依赖)文件时我遇到了链接问题。任何人都可以通过错误

向我指出正确的方向

...../part1.o: file not recognized: File truncated recipe for target 'bin/target/prog' failed

这是一个简单的程序,包含: main.cpp,part1.cpp,part1.h,part2.cpp,part2.h

part1和part2有一种打印方法。

运行make时来自终端

我不知道为什么我会收到使用 #pragma一次的警告?

stud@GoldenImageASE:~/Desktop/ISU/L1/2$ make ARCH=target -f Makefile.th
Compiling...part2.cpp
arm-devkit-g++ -MTbuild/target/part2.o -MM -I. part2.cpp > build/target/part2.d
Compiling...part1.cpp
arm-devkit-g++ -MTbuild/target/part1.o -MM -I. part1.cpp > build/target/part1.d
Compiling...main.cpp
arm-devkit-g++ -MTbuild/target/main.o -MM -I. main.cpp > build/target/main.d
object file....main.o
arm-devkit-g++ -I. -c main.cpp part1.h part2.h > build/target/main.o
part1.h:1:9: warning: #pragma once in main file
 #pragma once
         ^
part2.h:1:9: warning: #pragma once in main file
 #pragma once
         ^
object file....part1.o
arm-devkit-g++ -I. -c part1.cpp > build/target/part1.o
object file....part2.o
arm-devkit-g++ -I. -c part2.cpp > build/target/part2.o
arm-devkit-g++ -I. -o build/target/main.o build/target/part1.o build/target/part2.o -o prog
build/target/part1.o: file not recognized: File truncated
collect2: error: ld returned 1 exit status
Makefile.th:27: recipe for target 'bin/target/prog' failed
make: *** [bin/target/prog] Error 1

我的Makefile位于以下位置:

# Variables
SOURCES=main.cpp part1.cpp part2.cpp
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)
EXE=prog
CXXFLAGS =-I.


# Making for host
# > make ARCH=host
ifeq (${ARCH},host)
CXX=g++
BUILD_DIR=build/host
EXE_DIR=bin/host
endif

# Making for target
# > make ARCH= target
ifeq (${ARCH},target)
CXX=arm-devkit-g++
BUILD_DIR=build/target
EXE_DIR=bin/target
endif

$(addprefix ${EXE_DIR}/,$(EXE)): $(addprefix ${BUILD_DIR}/,$(DEPS)) $(addprefix ${BUILD_DIR}/,$(OBJECTS))
# << Check the $(DEPS) new dependency
    @mkdir -p $(dir $@)
    $(CXX) $(CXXFLAGS) -o $(addprefix ${BUILD_DIR}/,$(OBJECTS))

$(addprefix $(BUILD_DIR)/, %.o): %.cpp
    @echo "object file...."$*.o
    $(CXX) $(CXXFLAGS) -c $^ > $@


# Rule that describes how a .d ( dependency ) file is created from a .cpp
# Similar to the assigment %. cpp -> %.o
${BUILD_DIR}/%.d: %.cpp
    @mkdir -p $(dir $@)
    @echo "Compiling..."$<
    $(CXX) -MT$(@:.d=.o) -MM $(CXXFLAGS) $^ > $@

debug:
    @echo "DEPS: "$(DEPS)"\n"
    @echo "OBJ: " $(addprefix ${BUILD_DIR}/,$(OBJECTS))"\n"
    @echo "EXE: " $(addprefix ${EXE_DIR}/,$(EXE))"\n"


.PHONY:clean
clean: 
    rm -f $(EXE) $(addprefix ${BUILD_DIR}/,$(DEPS)) $(addprefix ${BUILD_DIR}/,$(OBJECTS))

ifneq ($(MAKECMDGOALS),clean)
-include $(addprefix ${BUILD_DIR}/,$(DEPS))
endif

2 个答案:

答案 0 :(得分:4)

你有两个无关的问题。第一个是链接时有两个有冲突的-o选项。

您询问的实际问题有所不同,但仍与-o选项有关:即在尝试创建目标文件时没有。

创建目标文件时,生成的目标文件写入标准输出,因此重定向不会导致gcc前端程序创建名称为您的目标文件认为

例如:

arm-devkit-g++ -I. -c part1.cpp > build/target/part1.o

上述命令将在当前目录中创建一个名为part1.o的目标文件,并将(空)标准输出写入文件build/target/part1.o。这将使build/target/part1.o为空,这就是链接器所抱怨的内容(这就是说文件被截断时的含义)。

该命令应该看起来像

arm-devkit-g++ -I. -c part1.cpp -o build/target/part1.o

请注意使用-o选项命名输出文件。

在构建目标文件时,您需要修改makefile以不使用重定向。

此外,在构建目标文件时,不应列出头文件,只应列出要构建的源文件,因此命令

arm-devkit-g++ -I. -c main.cpp part1.h part2.h > build/target/main.o

应该是

arm-devkit-g++ -I. -c main.cpp -o build/target/main.o

答案 1 :(得分:2)

您没有正确编译目标文件。 g++没有将文件输出到stdout,它直接将它们写入本地。如果要将目标文件放在特定目录中,则需要使用-o选项:

$(BUILD_DIR)/%.o: %.cpp | $(BUILD_DIR)
    $(CXX) $(CXXFLAGS) -c $^ -o $@
                            ^^^^^^

$(BUILD_DIR):
    @mkdir -p $@

此外,您还错误地构建了可执行文件。依赖关系不足,您没有列出您的目标。你会想要这个:

$(EXE_DIR)/$(EXE) : $(addprefix $(BUILD_DIR),$(OBJECTS)) | $(EXE_DIR)
    $(CXX) $(CXXFLAGS) -o $@ $^

$(EXE_DIR):
    @mkdir -p $@

这将从目录中的二进制文件创建一个仅订单依赖项,并正确构建二进制文件。请注意,您的.d文件不应与目标有依赖关系。这没什么意义。相反,构建.o的规则也应该只构建.d s(该规则目前遇到与.o规则相同的问题):

# build the .o and the .d in one go
$(BUILD_DIR)/%.o : %.cpp | $(BUILD_DIR)
    $(CXX) $(CXXFLAGS) -o $@ -c $< -MP -MMD -MF $(@:.o=.d)

作为一名社论者,在SHOUTY_CAPS中写下所有变量都是常见的趋势。使用snake_case只是阅读使用这一点非常困难。小写字母工作得很好。