c语言 - 未定义对'blink'的引用



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

dev-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

makefile:

.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 "onnnpn1nnntncnwn" | 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()的未定义引用。

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

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

并使用自动变量$@$<来消除更多的冗余:

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 $^
...

进一步的改进是可能的,但这就足够了。

有时候我想太多了。

正确的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 "onnnpn1nnntncnwn" | 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'命令之后。

最新更新