Неопределенная ссылка на «мигание»

#c #linux #makefile

Вопрос:

Я делаю .img для RPI-4 и т. Д. У меня есть основной файл init.c, который преобразуется в двоичный файл и в img. Теперь я хочу включить еще один файл .c с именем «src/dev-gpio.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
 

сделать файл:

     .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 ()? Независимо от того, что я делаю, я получаю неопределенную ссылку на blink() в моем init.c.

Комментарии:

1. Добро пожаловать в Stack Overflow. 1) Выясните, как строить dev-gpio.o в командной строке. 2) Как только это сработает, напишите для этого правило. 3) Измените команду связывания ( aarch64-linux-gnu-gcc ... ) в eos-init.bin правиле, возможно, просто добавив имя файла «dev-gpio.o» (с путем) в конец команды.

2. Теперь я добавил это правило для компиляции dev-gpio.o: 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 И изменил команду связывания на: build/rapi-boot/eos-init.bin: build/obj/init.o build/obj/dev-gpio.o и build/obj/dev-gpio.o добавил после запуска , но она все еще работает не совсем хорошо.

3. «Это все еще работает не совсем хорошо» — не очень хорошее описание проблемы, но я сделаю некоторые предположения и напишу ответ.

Ответ №1:

Насколько я понимаю, теперь у вас есть такое правило:

 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)

lt;

Как только мы убедимся, что это правило работает, мы изменим правило связывания, включив в него новый объектный файл ( 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 $^
    ...
 

Возможны дальнейшие уточнения, но пока этого достаточно.

Комментарии:

1. Я совсем новичок в make-файлах, и это было как раз то, что я хотел понять, чтобы выполнить свой проект. Теперь, когда мы лучше понимаем друг друга и добавили переменные для устранения избыточности, работать с ними намного приятнее. Спасибо!

Ответ №2:

Иногда я слишком много думаю..

Правильный файл 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» и добавлено это в правило компоновщика выше, а также после команды «пуск».