makefile编译存在问题

我在make编译的时候一个汇编文件boot.S报错,如下图所示,但是当我单独使用gcc命令编译却一切正常(同样的参数),请问这是怎么回事?如何解决?

img

makefile如下:

toolchain := riscv64-unknown-elf-

GCC := $(toolchain)gcc 
AS    := $(toolchain)as
LD  := $(toolchain)ld
OBJCOPY  :=$(toolchain)objcopy

COPS := -g -O0 -Wall -nostdlib -nostdinc -Iinclude -mcmodel=medany -fno-PIE -fomit-frame-pointer -Wno-builtin-declaration-mismatch -ggdb -g

all: system
    $(OBJCOPY)  -O binary system kernel.bin

system:    ./kernel/main.o ./kernel/boot.o ./kernel/urat.o
    $(LD) -z muldefs -T ./kernel/linker.ld -o system ./kernel/main.o ./kernel/boot.o ./kernel/urat.o

main.o: ./kernel/main.c
    $(GCC) $(COPS) -c ./kernel/main.c

boot.o: ./kernel/boot.S
    $(GCC) $(COPS) -c ./kernel/boot.S 

urat.o: ./kernel/urat.c
    $(GCC) $(COPS) -c ./kernel/urat.c

clean:
    rm -rf ./kernel/*.o
    rm -rf system kernel.bin

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
根据错误提示信息可以看出,make 编译时出现了以下错误:

./kernel/boot.S: Assembler messages:
./kernel/boot.S:7: Error: illegal instruction

但是当使用 gcc 命令单独编译时却没有这个问题。这很可能是因为 makegcc 在编译时的参数不同导致的。

在你的 Makefile 中,boot.o 的编译语句为:

$(GCC) $(COPS) -c ./kernel/boot.S

其中,$(COPS) 包含了一些编译参数,可能是这些参数导致了问题。建议一步一步进行调试。

可以先将 -c 参数去掉,将 boot.S 编译为汇编文件,如下所示:

$(AS) -o ./kernel/boot.o ./kernel/boot.S

如果这一步没有问题,可以加上 -v 参数来查看 gcc 在编译时默认使用的参数,再与 $(COPS) 中的参数进行比对,看看是否有冲突。

最后,你可以尝试在 $(COPS) 中逐个排除参数,重新编译 boot.o 文件,找出导致问题的参数。

以下是经过修改的 Makefile

toolchain := riscv64-unknown-elf-

GCC := $(toolchain)gcc 
AS    := $(toolchain)as
LD  := $(toolchain)ld
OBJCOPY  :=$(toolchain)objcopy

# COPS := -g -O0 -Wall -nostdlib -nostdinc -Iinclude -mcmodel=medany -fno-PIE -fomit-frame-pointer -Wno-builtin-declaration-mismatch -ggdb -g
COPS := -g -O0 -Wall -mcmodel=medany -fno-PIE -fomit-frame-pointer 

all: system
    $(OBJCOPY)  -O binary system kernel.bin

system:    ./kernel/main.o ./kernel/boot.o ./kernel/urat.o
    $(LD) -z muldefs -T ./kernel/linker.ld -o system ./kernel/main.o ./kernel/boot.o ./kernel/urat.o

main.o: ./kernel/main.c
    $(GCC) $(COPS) -c ./kernel/main.c

boot.o: ./kernel/boot.S
    $(AS) -o ./kernel/boot.o ./kernel/boot.S 

urat.o: ./kernel/urat.c
    $(GCC) $(COPS) -c ./kernel/urat.c

clean:
    rm -rf ./kernel/*.o
    rm -rf system kernel.bin

注意,我在 $(COPS) 中注释掉了 -nostdlib-nostdinc 参数,这两个参数会排除标准库和标准头文件,这对你的项目可能不是必须的。
如果我的回答解决了您的问题,请采纳!

参考GPT的内容和自己的思路,根据错误信息,可以看到在 kernel/boot.S 中存在汇编指令的问题,该汇编指令可能在GCC版本和assembler版本之间存在差异,因此需要进一步了解问题所在。

一种可能是,GCC和AS之间的默认指令集不同,导致在汇编boot.S时出现了错误。你可以通过在Makefile中指定AS的版本,例如:

AS := $(toolchain)as -march=rv64imafd


另一种可能是,GCC和AS在默认情况下使用不同的ABI。可以通过在Makefile中指定ABI来解决此问题,例如:

COPS := -g -O0 -Wall -nostdlib -nostdinc -Iinclude -mcmodel=medany -fno-PIE -fomit-frame-pointer -Wno-builtin-declaration-mismatch -ggdb -g -mabi=lp64


你可以尝试在Makefile中添加上述选项,重新运行make,看看能否解决问题。如果还有其他问题,请检查汇编指令是否与当前使用的指令集和ABI兼容。
回答不易,还请能采纳!!!

“Devil组”引证GPT后的撰写:
为boot.S使用GCC作为汇编器,这是不正确的。汇编器应该使用as命令而不是GCC。因此,要将以下行:

boot.o: ./kernel/boot.S
    $(GCC) $(COPS) -c ./kernel/boot.S


更改为:

boot.o: ./kernel/boot.S
    $(AS) $(COPS) -c ./kernel/boot.S


这将确保使用正确的汇编器编译汇编文件,并且应该解决您遇到的问题。

此外,您需要修复kernel/main.c中的函数调用警告,即添加头文件以声明uart函数。如果您使用的是uart.h文件,则可以在文件开头添加以下行:

#include "uart.h"


没有该文件,则需要创建它并将uart函数声明添加到其中,例如:

#ifndef __UART_H__
#define __UART_H__

void uart_init();
void uart_send_string(const char* str);

#endif /* __UART_H__ */