===== 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 [[https://en.wikipedia.org/wiki/Shell_(computing)|shell]] (na GNU/Linuxu obvykle [[https://www.gnu.org/software/bash/|BASH]] nebo [[https://en.wikipedia.org/wiki/Almquist_shell|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 ([[https://en.wikipedia.org/wiki/Make_%28software%29|Make]], [[https://ant.apache.org/|Ant]], [[https://en.wikipedia.org/wiki/Qmake|qmake]], [[https://cmake.org/|Cmake]], [[http://mesonbuild.com/|meson]], atd.).
===Makefile===
[[https://en.wikipedia.org/wiki/Make_%28software%29|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 [[https://en.wikipedia.org/wiki/Executable_and_Linkable_Format|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