对 'blink' 的未定义引用

Undefined Reference to 'blink'

我正在为 RPI-4 等制作 .img。我有一个主 init.c 文件,可以转换为二进制文件和 img。 现在我想合并另一个名为 'src/dev-gpio.c' 的 .c 文件。此文件包含一个在 init.c 的主循环中调用的 blink() 函数。

开发-gpio.c :

#include "eos.h"
void blink()
{ 
...
}

eos.h :

#ifndef EOS_H
#define EOS_H

#include <stdint.h>
#include <inttypes.h>
...
extern void blink();
#endif

生成文件:

    .PHONY: all build clean

build/rapi-boot/eos-init.bin: build/obj/init.o
    aarch64-linux-gnu-gcc -o eos-init.elf -nostdlib -fno-pie -nostartfiles -ffreestanding -T linker.ld -e start build/obj/init.o
    aarch64-linux-gnu-objcopy eos-init.elf -O binary -j .eos-* build/rapi-boot/eos-init.bin
    rm eos-init.elf

build/obj/init.o: src/init.c src/eos.h 
    aarch64-linux-gnu-gcc -o build/obj/init.o -c -fno-pie -ffreestanding src/init.c

build: build/rapi-boot/eos-init.bin
    dd if=/dev/zero of=build/eos.img count=100 bs=1M
    sudo losetup -D
    sudo losetup -fP build/eos.img
    printf "o\nn\np\n1\n\n\nt\nc\nw\n" | sudo fdisk /dev/loop0
    sudo losetup -o 1048576 /dev/loop1 /dev/loop0
    sudo mkfs.vfat -n EOS /dev/loop1
    sudo mount /dev/loop1 build/mnt
    sudo cp -r build/rapi-boot/* build/mnt/.
    sudo umount build/mnt
    sudo losetup -D

clean:
    if [ -f "build/rapi-boot/eos-init.bin" ]; then rm build/rapi-boot/eos-init.bin; fi
    if [ -f "build/eos.img" ]; then rm build/eos.img; fi
    if [ -f "build/obj/init.o" ]; then rm build/obj/*.o; fi
    if [ -f "build/obj/dev-gpio.o" ]; then rm build/obj/*.o; fi

我如何将这个 dev-gpio.c 文件添加到 makefile 以便我的 init.c 可以看到 blink() 函数?无论我做什么,我都会在 init.c.

中得到对 blink() 的未定义引用

有时候我会想太多..

正确的 makefile 应该是这样的:

    .PHONY: all build clean

build/rapi-boot/eos-init.bin: build/obj/init.o build/obj/dev-gpio.o
    aarch64-linux-gnu-gcc -o eos-init.elf -nostdlib -fno-pie -nostartfiles -ffreestanding -T linker.ld -e start build/obj/init.o build/obj/dev-gpio.o
    aarch64-linux-gnu-objcopy eos-init.elf -O binary -j .eos-* build/rapi-boot/eos-init.bin
    rm eos-init.elf

build/obj/init.o: src/init.c src/eos.h
    aarch64-linux-gnu-gcc -o build/obj/init.o -c -fno-pie -ffreestanding src/init.c

build/obj/dev-gpio.o: src/dev-gpio.c src/eos.h
    aarch64-linux-gnu-gcc -o build/obj/dev-gpio.o -c -fno-pie -ffreestanding src/dev-gpio.c

build: build/rapi-boot/eos-init.bin
    dd if=/dev/zero of=build/eos.img count=100 bs=1M
    sudo losetup -D
    sudo losetup -fP build/eos.img
    printf "o\nn\np\n1\n\n\nt\nc\nw\n" | sudo fdisk /dev/loop0
    sudo losetup -o 1048576 /dev/loop1 /dev/loop0
    sudo mkfs.vfat -n EOS /dev/loop1
    sudo mount /dev/loop1 build/mnt
    sudo cp -r build/rapi-boot/* build/mnt/.
    sudo umount build/mnt
    sudo losetup -D

clean:
    if [ -f "build/rapi-boot/eos-init.bin" ]; then rm build/rapi-boot/eos-init.bin; fi
    if [ -f "build/eos.img" ]; then rm build/eos.img; fi
    if [ -f "build/obj/init.o" ]; then rm build/obj/*.o; fi

为第二个 .c 文件添加了规则 'dev-gpio.c' 并将其添加到上面的链接器规则以及 'start' 命令之后。

据我了解,您现在有这样的规则:

build/obj/dev-gpio.o: src/dev-gpio.c src/init.o src/eos.h
    aarch64-linux-gnu-gcc -o build/obj/dev-gpio.o -c -fno-pie -ffreestanding src/dev-gpio.c

这些先决条件之一 (src/init.o) 不属于那里。我们删除它:

build/obj/dev-gpio.o: src/dev-gpio.c src/eos.h
    aarch64-linux-gnu-gcc -o build/obj/dev-gpio.o -c -fno-pie -ffreestanding src/dev-gpio.c

我们将编译标志放在一个变量中,以使规则更易于阅读(并删除冗余,因为我们在其他地方使用相同的标志:

CFLAGS := -fno-pie -ffreestanding 

build/obj/dev-gpio.o: src/dev-gpio.c src/eos.h
    aarch64-linux-gnu-gcc -o build/obj/dev-gpio.o -c $(CFLAGS) src/dev-gpio.c

并使用 automatic variables $@$< 删除更多冗余:

build/obj/dev-gpio.o: src/dev-gpio.c src/eos.h
    aarch64-linux-gnu-gcc -o $@ -c $(CFLAGS) $<

一旦我们验证该规则有效, 我们修改链接规则以包含新的目标文件 (build/obj/dev-gpio.o):

build/rapi-boot/eos-init.bin: build/obj/init.o build/obj/dev-gpio.o
    aarch64-linux-gnu-gcc -o eos-init.elf -nostdlib -fno-pie -nostartfiles -ffreestanding -T linker.ld -e start build/obj/init.o build/obj/dev-gpio.o
    ...

(我怀疑我知道如何删除多余的命令,但我暂时不去管它们。)

然后,再次使用变量来清理它:

build/rapi-boot/eos-init.bin: build/obj/init.o build/obj/dev-gpio.o
    aarch64-linux-gnu-gcc -o eos-init.elf -nostdlib $(CFLAGS) -nostartfiles -T linker.ld -e start $^
    ...

可以进一步改进,但现在就足够了。