===== 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