对 '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 $^
...
可以进一步改进,但现在就足够了。
我正在为 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 $^
...
可以进一步改进,但现在就足够了。