【问题标题】:Makefile - .o: file not recognized: File truncated?Makefile - .o:文件无法识别:文件被截断?
【发布时间】:2017-01-19 04:02:14
【问题描述】:

我只是在学习 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 once 的警告?

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

【问题讨论】:

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


    【解决方案1】:

    你有两个不相关的问题。第一个是您在链接时有两个冲突的-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
    

    【讨论】:

      【解决方案2】:

      您没有正确编译目标文件。 g++ 不会将文件输出到标准输出,而是直接将它们写入本地。如果要将目标文件放在特定目录中,则需要使用-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 文件。这没什么意义。相反,您构建.os 的规则也应该简单地构建.ds(该规则目前与您的.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)
      

      顺便说一句,在 MAKEFILE 中使用 SHOUTY_CAPS 编写所有变量是一种普遍趋势。事实证明,这比使用snake_case 更难阅读。小写字母工作得很好。

      【讨论】:

      • 感谢您的帮助和建议 :) 我已经更新了 makefile 但是我遇到了错误 main.o: file not Recogniz: File format not Recognized In recipe for target 'bin/host /prog'。
      • @Mat0 请不要用别人给你的答案来编辑你的问题。我已恢复您的编辑。
      猜你喜欢
      • 2020-08-09
      • 2011-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-10
      相关资源
      最近更新 更多