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