首页 > 解决方案 > 为什么目标“mykernel.bin”的配方失败了?

问题描述

我正在尝试使用 Ubuntu 创建一个简单的 mykernel.bin 文件。

GPPPARAM = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exception -fno-leading-underscore
ASPARAMS = --32
LDPARAMS = -m elf_i386
objects = loader.o kernel.o

%o: %.cpp
    g++ $(GPPPARAM) -o $@ -c $<

%o: %.s
    as $(ASPARAMS) -o $@ $<

mykernel.bin : linker.ld $(objects)
    ld $(LDPARAMS) -T $< -o $@ $(objects)

输出是:

make mykernel.bin ld -m elf_i386 -T linker.ld -o mykernel.bin loader.o kernel.o ld: i386:x86-64 architecture of input file loader.o' is incompatible with i386 output ld: i386:x86-64 architecture of input filekernel.o' is in compatible with i386 output Makefile:13: recipe for目标 'mykernel.bin' 失败 make: *** [mykernel.bin] 错误 1

标签: makefile

解决方案


如果你要显示完整的输出,包括你的目标文件的编译行,那么很明显你的编译器标志没有被用来编译你的源代码。因此,生成的目标文件适用于您的本机操作系统,当您需要 32 位时,它很可能是 64 位。

原因正如我上面所描述的:您的模式规则是错误的。你%o : %.cpp想写的时候就写了%.o : %.cpp。您编写的模式规则告诉 make 如果它想要构建一个文件loader.o(因此模式的 stem%o匹配loader.),它可以通过编译文件来实现loader..cpp(因为模式字符%in%.cpp被替换为 stem loader.)。由于没有loader..cpp文件,因此您的模式被丢弃为不匹配,并继续寻找另一个模式并找到一个,作为内置规则。

但是由于您使用的是非标准变量名称GPPPARAM而不是标准CXXFLAGS,因此默认规则不会使用您的任何标志。

您有两个选择:您可以修复您的模式规则,使其正确:

%.o: %.cpp
        g++ $(GPPPARAM) -o $@ -c $<

%.o: %.s
        as $(ASPARAMS) -o $@ $<

或者您可以摆脱自己的模式规则并使用 make 的内置规则,并设置标准变量以确保使用您的选项:

CXX := g++
CXXFLAGS := -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exception -fno-leading-underscore

AS := as
ASFLAGS := --32

推荐阅读