Bonus: Použití Makefile pro řízení překladu

Volání kompilátoru je vhodné minimálně dokumentovat a lépe zautomatizovat. Jednou z možností je vytvořit skript pro shell (na GNU/Linuxu obvykle BASH nebo DASH). Při překladu větších projektů je ale nepraktické překládat všechny kompilační jednotky opakovaně, když dojde k malé změně jen v některém ze zdrojových souborů. proto bylo vytvořeno množství programů speciálně navržených pro účel překladu a sestavení programu (Make, Ant, qmake, Cmake, meson, atd.).

Makefile

Make je nástroj pro automatickou kompilaci zdrojových kódů, potřebná konfigurace je uložena v souboru Makefile.

Makefile šablona pro překlad zdrojového kódu v assembleru:

ARCH=riscv64-unknown-elf

SOURCES = change_me.S
TARGET_EXE = change_me

CC=$(ARCH)-gcc
CXX=$(ARCH)-g++
AS=$(ARCH)-as
LD=$(ARCH)-ld
OBJCOPY=$(ARCH)-objcopy

ARCHFLAGS += -mabi=ilp32
ARCHFLAGS += -march=rv32i
ARCHFLAGS += -fno-lto

CFLAGS  += -ggdb -Os -Wall
CXXFLAGS+= -ggdb -Os -Wall
AFLAGS  += -ggdb
LDFLAGS += -ggdb
LDFLAGS += -nostartfiles
LDFLAGS += -nostdlib
LDFLAGS += -static
#LDFLAGS += -specs=/opt/musl/riscv64-linux-gnu/lib/musl-gcc.specs

CFLAGS  += $(ARCHFLAGS)
CXXFLAGS+= $(ARCHFLAGS)
AFLAGS  += $(ARCHFLAGS)
LDFLAGS += $(ARCHFLAGS)

OBJECTS += $(filter %.o,$(SOURCES:%.S=%.o))
OBJECTS += $(filter %.o,$(SOURCES:%.c=%.o))
OBJECTS += $(filter %.o,$(SOURCES:%.cpp=%.o))

all : default

.PHONY : default clean dep all

%.o:%.S
	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c $< -o $@

%.o:%.c
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

%.o:%.cpp
	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<

%.s:%.c
	$(CC) $(CFLAGS) $(CPPFLAGS) -S $< -o $@

default : $(TARGET_EXE)

$(TARGET_EXE) : $(OBJECTS)
	$(CC) $(LDFLAGS) $^ -o $@

dep: depend

depend: $(SOURCES) $(glob *.h)
	echo '# autogenerated dependencies' > depend
ifneq ($(filter %.S,$(SOURCES)),)
	$(CC)  -D__ASSEMBLY__ $(AFLAGS) -w -E -M $(filter %.S,$(SOURCES)) \
	  >> depend
endif
ifneq ($(filter %.c,$(SOURCES)),)
	$(CC) $(CFLAGS) $(CPPFLAGS) -w -E -M $(filter %.c,$(SOURCES)) \
	  >> depend
endif
ifneq ($(filter %.cpp,$(SOURCES)),)
	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -w -E -M $(filter %.cpp,$(SOURCES)) \
	  >> depend
endif

clean:
	rm -f *.o *.a $(OBJECTS) $(TARGET_EXE) depend

#riscv64-unknown-elf --source change_me

-include depend

Odsazení řádku v Makefile musí být pomocí tabulátoru. Makefile nerozezná odsazení pomocí mezer.

Sestavovací soubor Makefile se sestává z definic (přiřazení hodnot proměnným) a pravidel. Pravidla začínají řádkou, která určuje závislost cílů na jejich závislostech uvedených za dvojtečkou. Pravidla mohou přímo uvádět jména souborů nebo mohou být obecná, kdy zástupným znakem pro doplňovanou část jména je znak procento “%”. Kompletnější šablonu pro překlad na cílovou architekturu RISC-V i s nalezením závislostí na hlavičkových souborech naleznete na počítačích v laboratoři v adresáři /opt/apo/qtrvsim_template.

Kompilace

Kompilace probíhá příkazem make (příkaz make je nutné zadávat v adresáři, ve kterém je upravený Makefile a zdrojový kód programu). Make vygeneruje několik souborů, z nichž pro import do simulačního prostředí QtRvSim použijeme soubor bez koncovky. Překlad nejdříve převádí kompilační jednotky (jednotka je zjednodušeně jeden zdrojový soubor včetně vložených hlavičkových souborů) do objektového tvaru (.o) v relokovatelné podobě. Objektové soubory jsou linkerem složeny, vzájemné reference/odkazy vyřešeny a provedeno umístění na finální adresy. Pro uložení vlastních instrukcí strojového kódu je potřeba přidat obálku s informacemi, kde je potřeba kód upravit při konečném umístění .o souborů. Data a instrukce v konečném spustitelném tvaru je také potřeba doplnit informací na které adresy má být daná část/sekce umístěna. K uložení těchto informací je v našem případě a obecně na většině standardům odpovídajících systémů použitý formát ELF (Executable and Linkable Format).

Zjištění adres proměnných a korespondence zdrojového kódu a výsledného ELF souboru

Zjištění adres, na které byly jednotlivé funkce a datové položky linkerem umístěny lze zjistit

riscv64-unknown-elf-nm program

Rozmístění sekcí

riscv64-unknown-elf-objdump --headers program

Porovnání vstupu a výsledku překladu

riscv64-unknown-elf-objdump --source program

courses/b35apo/tutorials/03/makefile.txt · Last modified: 2024/02/02 18:41 (external edit)