diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 655f1e22..dd44795f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -79,10 +79,10 @@ jobs: name: helioscli-artifacts path: ./HeliosCLI - name: Set execute permissions for test script - run: chmod +x ./runtests.sh + run: chmod +x ./run_tests.sh working-directory: tests - name: Run general tests - run: ./runtests.sh + run: ./run_tests.sh working-directory: tests embedded: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aed70e16..f88bbc24 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,10 +37,10 @@ jobs: name: helioscli-artifacts path: ./HeliosCLI - name: Set execute permissions for test script - run: chmod +x ./runtests.sh + run: chmod +x ./run_tests.sh working-directory: tests - name: Run general tests - run: ./runtests.sh + run: ./run_tests.sh working-directory: tests embedded: diff --git a/HeliosCLI/Makefile b/HeliosCLI/Makefile index e4d245c4..c5cb9cdb 100644 --- a/HeliosCLI/Makefile +++ b/HeliosCLI/Makefile @@ -34,6 +34,14 @@ ifneq ($(INCLUDES),) CFLAGS+=$(INCLUDES) endif +# Architecture passed from parent Makefile (default to x64 if run standalone) +ARCH ?= x64 + +# Build and Output directories relative to this Makefile +BUILD_DIR = $(ARCH) +OUTPUT_DIR = output +FINAL_TARGET = $(OUTPUT_DIR)/helios_cli + # local NONSTANDARD libraries to link with # these MUST be exact filenames, cannot be -l syntax # for example: @@ -59,13 +67,19 @@ else $(shell find . -type f -name '*.cpp') endif -# object files are source files with .c replaced with .o -OBJS=\ - $(SRC:.cpp=.o) \ +# Separate source files by directory +HELIOS_SRC = $(shell find ../Helios -type f -name '*.cpp') +LOCAL_SRC = $(shell find . -type f -name '*.cpp') -# dependency files are source files with .c replaced with .d -DFILES=\ - $(SRC:.cpp=.d) \ +# Generate object file paths using BUILD_DIR +HELIOS_OBJS = $(patsubst ../Helios/%.cpp,$(BUILD_DIR)/Helios/%.o,$(HELIOS_SRC)) +LOCAL_OBJS = $(patsubst ./%.cpp,$(BUILD_DIR)/%.o,$(LOCAL_SRC)) +OBJS = $(HELIOS_OBJS) $(LOCAL_OBJS) + +# dependency files +HELIOS_DFILES = $(patsubst ../Helios/%.cpp,$(BUILD_DIR)/Helios/%.d,$(HELIOS_SRC)) +LOCAL_DFILES = $(patsubst ./%.cpp,$(BUILD_DIR)/%.d,$(LOCAL_SRC)) +DFILES = $(HELIOS_DFILES) $(LOCAL_DFILES) # target dependencies # this includes any script generated c/h files, @@ -87,12 +101,18 @@ all: $(TARGETS) # unit test target tests: $(TESTS) -# target for vortex lib +# target for helios cli helios: compute_version $(DEPS) - $(CC) $(CFLAGS) $(DEPS) -o $@ $(LLIBS) + @mkdir -p $(OUTPUT_DIR) + $(CC) $(CFLAGS) $(OBJS) -o $(FINAL_TARGET) $(LLIBS) -# catch-all make target to generate .o and .d files -%.o: %.cpp +# Rules for building object files +$(BUILD_DIR)/Helios/%.o: ../Helios/%.cpp + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -MMD -c $< -o $@ + +$(BUILD_DIR)/%.o: ./%.cpp + @mkdir -p $(dir $@) $(CC) $(CFLAGS) -MMD -c $< -o $@ # catch-all for static libraries in the form of: @@ -107,7 +127,8 @@ FORCE: # generic clean target clean: - @$(RM) $(DFILES) $(OBJS) $(TARGETS) $(TESTS) + @$(RM) -rf $(BUILD_DIR) $(OUTPUT_DIR) + @$(RM) -f $(DFILES) $(OBJS) $(TESTS) compute_version: $(eval LATEST_TAG ?= $(shell git fetch --depth=1 origin +refs/tags/*:refs/tags/* &> /dev/null && git tag --list | sort -V | tail -n1)) @@ -121,18 +142,43 @@ compute_version: $(eval HELIOS_BUILD_NUMBER := $(if $(HELIOS_BUILD_NUMBER),$(HELIOS_BUILD_NUMBER),0)) $(eval HELIOS_VERSION_NUMBER := $(HELIOS_VERSION_MAJOR).$(HELIOS_VERSION_MINOR).$(HELIOS_BUILD_NUMBER)) +# generate bmps +bmps: + ./PatternGenerator/generate_bmps.sh -c + # generate svg svgs: bmps - ./generate_svgs.sh + ./PatternGenerator/generate_svgs.sh # generate pngs pngs: bmps - ./generate_pngs.sh + ./PatternGenerator/generate_pngs.sh -# generate pngs -bmps: - ./generate_bmps.sh -c +# record tests +record_tests: all + ../tests/record_tests.sh + +# record test +record_test: all + ../tests/record_test.sh + +# run tests +run_tests: all + ../tests/run_tests.sh + +# create_tests +create_tests: all + ../tests/create_test.sh + +# export tests +export_tests: all + ../tests/export_tests.sh + +# import tests +import_tests: all + ../tests/import_tests.sh +# clean storage clean_storage: @echo "Cleaning Helios storage file..." @$(RM) Helios.storage diff --git a/HeliosCLI/convert_bmp_to_png.py b/HeliosCLI/PatternGenerator/convert_bmp_to_png.py similarity index 100% rename from HeliosCLI/convert_bmp_to_png.py rename to HeliosCLI/PatternGenerator/convert_bmp_to_png.py diff --git a/HeliosCLI/convert_bmp_to_svg.py b/HeliosCLI/PatternGenerator/convert_bmp_to_svg.py similarity index 100% rename from HeliosCLI/convert_bmp_to_svg.py rename to HeliosCLI/PatternGenerator/convert_bmp_to_svg.py diff --git a/HeliosCLI/default_patterns/001_Lightside.pattern b/HeliosCLI/PatternGenerator/default_patterns/001_Lightside.pattern similarity index 100% rename from HeliosCLI/default_patterns/001_Lightside.pattern rename to HeliosCLI/PatternGenerator/default_patterns/001_Lightside.pattern diff --git a/HeliosCLI/default_patterns/002_Sauna.pattern b/HeliosCLI/PatternGenerator/default_patterns/002_Sauna.pattern similarity index 100% rename from HeliosCLI/default_patterns/002_Sauna.pattern rename to HeliosCLI/PatternGenerator/default_patterns/002_Sauna.pattern diff --git a/HeliosCLI/default_patterns/003_Butterfly.pattern b/HeliosCLI/PatternGenerator/default_patterns/003_Butterfly.pattern similarity index 100% rename from HeliosCLI/default_patterns/003_Butterfly.pattern rename to HeliosCLI/PatternGenerator/default_patterns/003_Butterfly.pattern diff --git a/HeliosCLI/default_patterns/004_Freezer_Burn.pattern b/HeliosCLI/PatternGenerator/default_patterns/004_Freezer_Burn.pattern similarity index 100% rename from HeliosCLI/default_patterns/004_Freezer_Burn.pattern rename to HeliosCLI/PatternGenerator/default_patterns/004_Freezer_Burn.pattern diff --git a/HeliosCLI/default_patterns/005_Ice_Blade.pattern b/HeliosCLI/PatternGenerator/default_patterns/005_Ice_Blade.pattern similarity index 100% rename from HeliosCLI/default_patterns/005_Ice_Blade.pattern rename to HeliosCLI/PatternGenerator/default_patterns/005_Ice_Blade.pattern diff --git a/HeliosCLI/default_patterns/006_Rainbow_Glitter.pattern b/HeliosCLI/PatternGenerator/default_patterns/006_Rainbow_Glitter.pattern similarity index 100% rename from HeliosCLI/default_patterns/006_Rainbow_Glitter.pattern rename to HeliosCLI/PatternGenerator/default_patterns/006_Rainbow_Glitter.pattern diff --git a/HeliosCLI/default_patterns/007_Ribbon.pattern b/HeliosCLI/PatternGenerator/default_patterns/007_Ribbon.pattern similarity index 100% rename from HeliosCLI/default_patterns/007_Ribbon.pattern rename to HeliosCLI/PatternGenerator/default_patterns/007_Ribbon.pattern diff --git a/HeliosCLI/default_patterns/008_Ultra_Dops.pattern b/HeliosCLI/PatternGenerator/default_patterns/008_Ultra_Dops.pattern similarity index 100% rename from HeliosCLI/default_patterns/008_Ultra_Dops.pattern rename to HeliosCLI/PatternGenerator/default_patterns/008_Ultra_Dops.pattern diff --git a/HeliosCLI/default_patterns/009_Dops.pattern b/HeliosCLI/PatternGenerator/default_patterns/009_Dops.pattern similarity index 100% rename from HeliosCLI/default_patterns/009_Dops.pattern rename to HeliosCLI/PatternGenerator/default_patterns/009_Dops.pattern diff --git a/HeliosCLI/default_patterns/010_Strobe.pattern b/HeliosCLI/PatternGenerator/default_patterns/010_Strobe.pattern similarity index 100% rename from HeliosCLI/default_patterns/010_Strobe.pattern rename to HeliosCLI/PatternGenerator/default_patterns/010_Strobe.pattern diff --git a/HeliosCLI/default_patterns/011_Hypnostrobe.pattern b/HeliosCLI/PatternGenerator/default_patterns/011_Hypnostrobe.pattern similarity index 100% rename from HeliosCLI/default_patterns/011_Hypnostrobe.pattern rename to HeliosCLI/PatternGenerator/default_patterns/011_Hypnostrobe.pattern diff --git a/HeliosCLI/default_patterns/012_Strobie.pattern b/HeliosCLI/PatternGenerator/default_patterns/012_Strobie.pattern similarity index 100% rename from HeliosCLI/default_patterns/012_Strobie.pattern rename to HeliosCLI/PatternGenerator/default_patterns/012_Strobie.pattern diff --git a/HeliosCLI/default_patterns/013_Razor.pattern b/HeliosCLI/PatternGenerator/default_patterns/013_Razor.pattern similarity index 100% rename from HeliosCLI/default_patterns/013_Razor.pattern rename to HeliosCLI/PatternGenerator/default_patterns/013_Razor.pattern diff --git a/HeliosCLI/default_patterns/014_Flare.pattern b/HeliosCLI/PatternGenerator/default_patterns/014_Flare.pattern similarity index 100% rename from HeliosCLI/default_patterns/014_Flare.pattern rename to HeliosCLI/PatternGenerator/default_patterns/014_Flare.pattern diff --git a/HeliosCLI/default_patterns/015_Burst.pattern b/HeliosCLI/PatternGenerator/default_patterns/015_Burst.pattern similarity index 100% rename from HeliosCLI/default_patterns/015_Burst.pattern rename to HeliosCLI/PatternGenerator/default_patterns/015_Burst.pattern diff --git a/HeliosCLI/default_patterns/016_Glow.pattern b/HeliosCLI/PatternGenerator/default_patterns/016_Glow.pattern similarity index 100% rename from HeliosCLI/default_patterns/016_Glow.pattern rename to HeliosCLI/PatternGenerator/default_patterns/016_Glow.pattern diff --git a/HeliosCLI/default_patterns/017_Flicker.pattern b/HeliosCLI/PatternGenerator/default_patterns/017_Flicker.pattern similarity index 100% rename from HeliosCLI/default_patterns/017_Flicker.pattern rename to HeliosCLI/PatternGenerator/default_patterns/017_Flicker.pattern diff --git a/HeliosCLI/default_patterns/018_Flash.pattern b/HeliosCLI/PatternGenerator/default_patterns/018_Flash.pattern similarity index 100% rename from HeliosCLI/default_patterns/018_Flash.pattern rename to HeliosCLI/PatternGenerator/default_patterns/018_Flash.pattern diff --git a/HeliosCLI/default_patterns/019_Morph.pattern b/HeliosCLI/PatternGenerator/default_patterns/019_Morph.pattern similarity index 100% rename from HeliosCLI/default_patterns/019_Morph.pattern rename to HeliosCLI/PatternGenerator/default_patterns/019_Morph.pattern diff --git a/HeliosCLI/default_patterns/020_Morph_Strobe.pattern b/HeliosCLI/PatternGenerator/default_patterns/020_Morph_Strobe.pattern similarity index 100% rename from HeliosCLI/default_patterns/020_Morph_Strobe.pattern rename to HeliosCLI/PatternGenerator/default_patterns/020_Morph_Strobe.pattern diff --git a/HeliosCLI/default_patterns/021_Morph_Strobie.pattern b/HeliosCLI/PatternGenerator/default_patterns/021_Morph_Strobie.pattern similarity index 100% rename from HeliosCLI/default_patterns/021_Morph_Strobie.pattern rename to HeliosCLI/PatternGenerator/default_patterns/021_Morph_Strobie.pattern diff --git a/HeliosCLI/default_patterns/022_Morph_Glow.pattern b/HeliosCLI/PatternGenerator/default_patterns/022_Morph_Glow.pattern similarity index 100% rename from HeliosCLI/default_patterns/022_Morph_Glow.pattern rename to HeliosCLI/PatternGenerator/default_patterns/022_Morph_Glow.pattern diff --git a/HeliosCLI/default_patterns/023_Dash_Dops.pattern b/HeliosCLI/PatternGenerator/default_patterns/023_Dash_Dops.pattern similarity index 100% rename from HeliosCLI/default_patterns/023_Dash_Dops.pattern rename to HeliosCLI/PatternGenerator/default_patterns/023_Dash_Dops.pattern diff --git a/HeliosCLI/default_patterns/024_Dash_Dot.pattern b/HeliosCLI/PatternGenerator/default_patterns/024_Dash_Dot.pattern similarity index 100% rename from HeliosCLI/default_patterns/024_Dash_Dot.pattern rename to HeliosCLI/PatternGenerator/default_patterns/024_Dash_Dot.pattern diff --git a/HeliosCLI/default_patterns/025_Wave_Particle.pattern b/HeliosCLI/PatternGenerator/default_patterns/025_Wave_Particle.pattern similarity index 100% rename from HeliosCLI/default_patterns/025_Wave_Particle.pattern rename to HeliosCLI/PatternGenerator/default_patterns/025_Wave_Particle.pattern diff --git a/HeliosCLI/default_patterns/026_Lightspeed.pattern b/HeliosCLI/PatternGenerator/default_patterns/026_Lightspeed.pattern similarity index 100% rename from HeliosCLI/default_patterns/026_Lightspeed.pattern rename to HeliosCLI/PatternGenerator/default_patterns/026_Lightspeed.pattern diff --git a/HeliosCLI/generate_bmps.sh b/HeliosCLI/PatternGenerator/generate_bmps.sh similarity index 100% rename from HeliosCLI/generate_bmps.sh rename to HeliosCLI/PatternGenerator/generate_bmps.sh diff --git a/HeliosCLI/generate_pngs.sh b/HeliosCLI/PatternGenerator/generate_pngs.sh similarity index 100% rename from HeliosCLI/generate_pngs.sh rename to HeliosCLI/PatternGenerator/generate_pngs.sh diff --git a/HeliosCLI/generate_svgs.sh b/HeliosCLI/PatternGenerator/generate_svgs.sh similarity index 100% rename from HeliosCLI/generate_svgs.sh rename to HeliosCLI/PatternGenerator/generate_svgs.sh diff --git a/HeliosEmbedded/Makefile b/HeliosEmbedded/Makefile index 41308e34..dacd0cda 100644 --- a/HeliosEmbedded/Makefile +++ b/HeliosEmbedded/Makefile @@ -141,18 +141,33 @@ CFLAGS+=$(INCLUDES) ### SOURCE FILES ###### ####################### +# Architecture passed from parent Makefile (default to avr if run standalone) +ARCH ?= avr + +# Build and Output directories relative to this Makefile +BUILD_DIR = $(ARCH) +LOCAL_OUTPUT_DIR = output + # Source files ifeq ($(OS),Windows_NT) # Windows -SRCS = \ - $(shell find ../Helios -maxdepth 1 -type f -name '\*.cpp') main.cpp -else # linux -SRCS = \ - $(shell find ../Helios -maxdepth 1 -type f -name \*.cpp) main.cpp +HELIOS_SRCS = \ + $(shell find ../Helios -maxdepth 1 -type f -name '\*.cpp') +LOCAL_SRCS = main.cpp +else # linux/macos +HELIOS_SRCS = \ + $(shell find ../Helios -maxdepth 1 -type f -name \*.cpp) +LOCAL_SRCS = main.cpp endif -OBJS = $(SRCS:.cpp=.o) +# Generate object file paths using BUILD_DIR +HELIOS_OBJS = $(patsubst ../Helios/%.cpp,$(BUILD_DIR)/Helios/%.o,$(HELIOS_SRCS)) +LOCAL_OBJS = $(patsubst %.cpp,$(BUILD_DIR)/%.o,$(LOCAL_SRCS)) +OBJS = $(HELIOS_OBJS) $(LOCAL_OBJS) -DFILES = $(SRCS:.cpp=.d) +# Generate dependency file paths +HELIOS_DFILES = $(patsubst ../Helios/%.cpp,$(BUILD_DIR)/Helios/%.d,$(HELIOS_SRCS)) +LOCAL_DFILES = $(patsubst %.cpp,$(BUILD_DIR)/%.d,$(LOCAL_SRCS)) +DFILES = $(HELIOS_DFILES) $(LOCAL_DFILES) ####################### ### BUILD TARGETS ##### @@ -161,30 +176,50 @@ DFILES = $(SRCS:.cpp=.d) # Target name TARGET = helios -all: compute_version $(TARGET).hex +# Define final hex target (still goes to root output) +ROOT_OUTPUT_DIR = ../output # This needs to stay for the root makefile to copy +FINAL_HEX_TARGET = $(ROOT_OUTPUT_DIR)/helios_firmware.hex # Keep final target name + +# Define targets for intermediate files in local output +LOCAL_ELF_TARGET = $(LOCAL_OUTPUT_DIR)/$(TARGET).elf +LOCAL_BIN_TARGET = $(LOCAL_OUTPUT_DIR)/$(TARGET).bin +LOCAL_EEP_TARGET = $(LOCAL_OUTPUT_DIR)/$(TARGET).eep +LOCAL_LST_TARGET = $(LOCAL_OUTPUT_DIR)/$(TARGET).lst +LOCAL_MAP_TARGET = $(LOCAL_OUTPUT_DIR)/$(TARGET).map + +all: compute_version $(FINAL_HEX_TARGET) @echo Detected Operating System: $(OS) - $(OBJDUMP) --disassemble --source --line-numbers --demangle --section=.text $(TARGET).elf > $(TARGET).lst - $(NM) --numeric-sort --line-numbers --demangle --print-size --format=s $(TARGET).elf > $(TARGET).map + $(OBJDUMP) --disassemble --source --line-numbers --demangle --section=.text $(LOCAL_ELF_TARGET) > $(LOCAL_LST_TARGET) + $(NM) --numeric-sort --line-numbers --demangle --print-size --format=s $(LOCAL_ELF_TARGET) > $(LOCAL_MAP_TARGET) chmod +x avrsize.sh - ./avrsize.sh $(TARGET).elf + ./avrsize.sh $(LOCAL_ELF_TARGET) @echo "== Success building Helios v$(HELIOS_VERSION_NUMBER) ==" -$(TARGET).hex: $(TARGET).elf - $(OBJCOPY) -O binary -R .eeprom $(TARGET).elf $(TARGET).bin - $(OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $(TARGET).elf $(TARGET).eep - $(OBJCOPY) -O ihex -R .eeprom $< $@ +$(FINAL_HEX_TARGET): $(LOCAL_ELF_TARGET) + @mkdir -p $(dir $@) + @mkdir -p $(LOCAL_OUTPUT_DIR) + $(OBJCOPY) -O binary -R .eeprom $< $(LOCAL_BIN_TARGET) + $(OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $< $(LOCAL_EEP_TARGET) + $(OBJCOPY) -O ihex -R .eeprom $< ../output/helios_firmware.hex + @echo "Created final hex: ../output/helios_firmware.hex" -$(TARGET).elf: compute_version $(OBJS) +$(LOCAL_ELF_TARGET): compute_version $(OBJS) + @mkdir -p $(dir $@) $(LD) $(LDFLAGS) $(OBJS) -o $@ -%.o: %.S - $(CC) $(ASMFLAGS) -c $< -o $@ +# Rules for building object files +$(BUILD_DIR)/Helios/%.o: ../Helios/%.cpp + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -MM -MT "$@" -MF "$(BUILD_DIR)/Helios/$*.d" $< -%.o: %.cpp +$(BUILD_DIR)/%.o: %.cpp + @mkdir -p $(dir $@) $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -MM -MT "$@" -MF "$(BUILD_DIR)/$*.d" $< -upload: set_fuses $(TARGET).hex - $(AVRDUDE) $(AVRDUDE_FLAGS) -Uflash:w:$(TARGET).hex:i +upload: set_fuses $(FINAL_HEX_TARGET) + $(AVRDUDE) $(AVRDUDE_FLAGS) -Uflash:w:$(FINAL_HEX_TARGET):i ####################### ### LINUX SETUP ####### @@ -284,7 +319,11 @@ extract_hex: helios_firmware.hex ##################### clean: - rm -f $(OBJS) $(TARGET).elf $(TARGET).hex $(DFILES) $(TARGET).bin $(TARGET).eep $(TARGET).lst $(TARGET).map + @echo "Cleaning up HeliosEmbedded..." + @$(RM) -rf $(BUILD_DIR) $(LOCAL_OUTPUT_DIR) + @$(RM) -f $(OBJS) $(DFILES) # Keep FINAL_HEX_TARGET out of here, root cleans it + @$(RM) -f *.d ../Helios/*.d + @echo "Cleaned HeliosEmbedded!" compute_version: $(eval LATEST_TAG ?= $(shell git fetch --depth=1 origin +refs/tags/*:refs/tags/* &> /dev/null && git tag --list | sort -V | tail -n1)) diff --git a/HeliosLib/Makefile b/HeliosLib/Makefile index 97eacfe6..cf8299dc 100644 --- a/HeliosLib/Makefile +++ b/HeliosLib/Makefile @@ -66,25 +66,36 @@ LLIBS=\ LIBS=\ $(LLIBS) \ +# Architecture passed from parent Makefile (default to x64 if run standalone) +ARCH ?= x64 + +# Build and Output directories relative to this Makefile +BUILD_DIR = $(ARCH) +OUTPUT_DIR = output +FINAL_LIB_TARGET = $(OUTPUT_DIR)/helios_lib.a +FINAL_WASM_TARGET = $(OUTPUT_DIR)/helios_wasm.js +FINAL_WASM_BIN_TARGET = $(OUTPUT_DIR)/helios_wasm.wasm + # source files -# local source files first, other sources after ifeq ($(OS),Windows_NT) - SRC = $(shell find ../Helios/ -type f -name \\*.cpp) HeliosLib.cpp + HELIOS_SRC = $(shell find ../Helios/ -type f -name \\*.cpp) + LOCAL_SRC = HeliosLib.cpp else - SRC = $(shell find ../Helios/ -type f -name '*.cpp') HeliosLib.cpp + HELIOS_SRC = $(shell find ../Helios/ -type f -name '*.cpp') + LOCAL_SRC = HeliosLib.cpp endif -# object files are source files with .c replaced with .o -OBJS=\ - $(SRC:.cpp=.o) \ +# Generate object file paths using BUILD_DIR +HELIOS_OBJS = $(patsubst ../Helios/%.cpp,$(BUILD_DIR)/Helios/%.o,$(HELIOS_SRC)) +LOCAL_OBJS = $(patsubst %.cpp,$(BUILD_DIR)/%.o,$(LOCAL_SRC)) +OBJS = $(HELIOS_OBJS) $(LOCAL_OBJS) -# dependency files are source files with .c replaced with .d -DFILES=\ - $(SRC:.cpp=.d) \ +# Generate dependency file paths +HELIOS_DFILES = $(patsubst ../Helios/%.cpp,$(BUILD_DIR)/Helios/%.d,$(HELIOS_SRC)) +LOCAL_DFILES = $(patsubst %.cpp,$(BUILD_DIR)/%.d,$(LOCAL_SRC)) +DFILES = $(HELIOS_DFILES) $(LOCAL_DFILES) # target dependencies -# this includes any script generated c/h files, -# the $(LLIBS) list, and the $(OBJS) list DEPS=\ $(LLIBS) \ $(OBJS) \ @@ -94,10 +105,9 @@ TESTS=\ # target files ifdef WASM -TARGETS=HeliosLib.js \ - helios.a +TARGETS=$(FINAL_WASM_TARGET) $(FINAL_LIB_TARGET) else -TARGETS=helios.a +TARGETS=$(FINAL_LIB_TARGET) endif # Default target for 'make' command @@ -108,25 +118,45 @@ tests: $(TESTS) # force sub-build of wasm wasm: FORCE - env WASM=1 $(MAKE) + @if command -v em++; then \ + echo "WebAssembly compiler found, building WASM..."; \ + env ARCH=wasm WASM=1 $(MAKE) $(FINAL_WASM_TARGET) $(FINAL_LIB_TARGET); \ + else \ + echo "WebAssembly compiler (em++) not found, skipping WASM build."; \ + mkdir -p $(OUTPUT_DIR); \ + touch $(FINAL_WASM_TARGET); \ + touch $(FINAL_WASM_BIN_TARGET); \ + fi # target for helios lib -helios.a: compute_version $(DEPS) +$(FINAL_LIB_TARGET): compute_version $(DEPS) + @mkdir -p $(dir $@) $(AR) $@ $(DEPS) + @echo "Created $@" -HeliosLib.js: compute_version $(DEPS) +# target for HeliosLib.js +$(FINAL_WASM_TARGET): compute_version $(DEPS) + @mkdir -p $(dir $@) $(CC) $(LDFLAGS) $(DEPS) -o $@ $(LLIBS) -# catch-all make target to generate .o and .d files -%.o: %.cpp +# Rules for building object files +$(BUILD_DIR)/Helios/%.o: ../Helios/%.cpp + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -MMD -c $< -o $@ + +$(BUILD_DIR)/%.o: %.cpp + @mkdir -p $(dir $@) $(CC) $(CFLAGS) -MMD -c $< -o $@ -# Empty rule that forces %.a to run all the time +# Empty rule that forces .a to run all the time FORCE: # generic clean target clean: - @$(RM) $(DFILES) $(OBJS) $(TARGETS) $(TESTS) HeliosLib.js HeliosLib.wasm + @echo "Cleaning up HeliosLib..." + @$(RM) -rf $(BUILD_DIR) $(OUTPUT_DIR) + @$(RM) -f $(DFILES) $(OBJS) $(TESTS) HeliosLib.js HeliosLib.wasm # Remove old possible output names + @echo "Cleaned HeliosLib!" compute_version: $(eval LATEST_TAG ?= $(shell git fetch --depth=1 origin +refs/tags/*:refs/tags/* &> /dev/null && git tag --list | sort -V | tail -n1)) diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..48d17320 --- /dev/null +++ b/Makefile @@ -0,0 +1,142 @@ +# Unified Makefile for Helios Engine +# This Makefile runs commands in subdirectories + +# List all make targets which are not filenames +.PHONY: all clean lib cli embedded tests wasm docs help package setup_root_output + +# Directories containing Makefiles +HELIOS_LIB_DIR = HeliosLib +HELIOS_CLI_DIR = HeliosCLI +HELIOS_EMBEDDED_DIR = HeliosEmbedded + +# Root output directory for aggregated artifacts +ROOT_OUTPUT_DIR = output + +# Setup root output directory +setup_root_output: + @echo "Setting up root output directory..." + @mkdir -p $(ROOT_OUTPUT_DIR) + +# Default target - Build the embedded version +embedded: setup_root_output + @echo "Building Helios Embedded..." + @$(MAKE) -C $(HELIOS_EMBEDDED_DIR) ARCH=avr + +# CLI builds lib implicitly +cli: setup_root_output + @echo "Building Helios CLI..." + @$(MAKE) -C $(HELIOS_CLI_DIR) ARCH=x64 + @cp $(HELIOS_CLI_DIR)/output/helios_cli $(ROOT_OUTPUT_DIR)/ + +# Build everything (truly "all") - but build them separately +all: + @echo "Building all components..." + @$(MAKE) embedded + @$(MAKE) cli + @$(MAKE) lib + @$(MAKE) wasm + @echo "All components built successfully" + +# Build the Helios library +lib: setup_root_output + @echo "Building Helios library..." + @$(MAKE) -C $(HELIOS_LIB_DIR) ARCH=x64 + @cp $(HELIOS_LIB_DIR)/output/helios_lib.a $(ROOT_OUTPUT_DIR)/ + +# Build WebAssembly version - HeliosLib will check for compiler availability +wasm: setup_root_output + @echo "Building WebAssembly library..." + @$(MAKE) -C $(HELIOS_LIB_DIR) wasm ARCH=wasm + @cp -f $(HELIOS_LIB_DIR)/output/helios_wasm.js $(ROOT_OUTPUT_DIR)/ 2>/dev/null || true + @cp -f $(HELIOS_LIB_DIR)/output/helios_wasm.wasm $(ROOT_OUTPUT_DIR)/ 2>/dev/null || true + +# Upload embedded firmware +upload: + @echo "Uploading firmware to device..." + @$(MAKE) -C $(HELIOS_EMBEDDED_DIR) upload + +# Generate PNGs for documentation +svgs: + @echo "Generating PNG files..." + @$(MAKE) -C $(HELIOS_CLI_DIR) svgs + @mkdir -p ./assets + @cp $(HELIOS_CLI_DIR)/*.png ./assets/ + +# Run tests +run_tests: cli + @echo "Running tests for Helios CLI..." + @$(MAKE) -C $(HELIOS_CLI_DIR) run_tests + +record_tests: cli + @echo "Recording tests for Helios CLI..." + @$(MAKE) -C $(HELIOS_CLI_DIR) record_tests + +create_tests: cli + @echo "Creating tests for Helios CLI..." + @$(MAKE) -C $(HELIOS_CLI_DIR) create_tests + +export_tests: cli + @echo "Exporting tests for Helios CLI..." + @$(MAKE) -C $(HELIOS_CLI_DIR) export_tests + +import_tests: cli + @echo "Importing tests for Helios CLI..." + @$(MAKE) -C $(HELIOS_CLI_DIR) import_tests + +# Clean all build artifacts and storage files +clean: + @echo "Cleaning Helios library..." + @$(MAKE) -C $(HELIOS_LIB_DIR) clean + @echo "Cleaning Helios CLI..." + @$(MAKE) -C $(HELIOS_CLI_DIR) clean + @echo "Cleaning Helios Embedded..." + @$(MAKE) -C $(HELIOS_EMBEDDED_DIR) clean + @echo "Cleaning storage files..." + @$(MAKE) -C $(HELIOS_CLI_DIR) clean_storage + @echo "Cleaning root directories..." + @rm -rf assets helios_package helios_package.zip $(ROOT_OUTPUT_DIR) + +# Package all compiled binaries into a zip file +package: + @echo "Packaging Helios binaries..." + @$(MAKE) all + @mkdir -p helios_package + @cp $(ROOT_OUTPUT_DIR)/* helios_package/ 2>/dev/null || true + @cp -r assets helios_package/ 2>/dev/null || true + @zip -r helios_package.zip helios_package + @rm -rf helios_package + @echo "Package created: helios_package.zip" + +# Help information +help: + @echo "Helios Engine Unified Build System" + @echo "" + @echo "Available targets:" + @echo " embedded - default, Build embedded firmware (output in HeliosEmbedded/output & ./output)" + @echo " cli - Build CLI tool (output in HeliosCLI/output & ./output)" + @echo " all - Build everything (outputs in component dirs & ./output)" + @echo " lib - Build library (output in HeliosLib/output & ./output)" + @echo " wasm - Build WebAssembly (output in HeliosLib/output & ./output)" + @echo " upload - Upload firmware from HeliosEmbedded/output/helios_firmware.hex" + @echo " run_tests - Run all tests" + @echo " record_tests - Record test outputs" + @echo " create_tests - Create a new test interactively" + @echo " export_tests - Export tests to CSV" + @echo " import_tests - Import tests from CSV" + @echo " svgs - Generate SVG documentation files" + @echo " clean - Clean all build artifacts, output files, and storage files" + @echo " package - Build all components and package ./output/* into a zip file" + @echo " help - Show this help information" + +# Important note for component Makefiles: +# To compile with the correct architecture settings and object file location, +# the following environment variables need to be used in the component Makefiles: +# +# 1. ARCH - Target architecture (avr, x64, wasm) +# 2. BUILD_DIR - Location for object files +# +# Object files should then be written to $(BUILD_DIR)/*.o instead of +# in the source directories. Source files in shared directories like +# ../Helios should create corresponding directories in $(BUILD_DIR). +# +# Example: ../Helios/Timer.cpp → $(BUILD_DIR)/Helios/Timer.o \ No newline at end of file diff --git a/tests/README.md b/tests/README.md index 54dcbd67..f12ff3a5 100644 --- a/tests/README.md +++ b/tests/README.md @@ -18,17 +18,17 @@ Tests are located in the `tests/` directory and are organized as individual `.te To run the tests: 1. Navigate to the `tests/` directory. -2. Run the `runtests.sh` script: +2. Run the `run_tests.sh` script: ```bash -./runtests.sh +./run_tests.sh ``` This script will execute all available tests and report the results. ### Test Options -The `runtests.sh` script supports several options: +The `run_tests.sh` script supports several options: - `-v`: Verbose mode. Provides more detailed output during test execution. - `-n`: No-make mode. Skips rebuilding the Helios executable before running tests. @@ -39,7 +39,7 @@ The `runtests.sh` script supports several options: Example usage: ```bash -./runtests.sh -v -t=5 +./run_tests.sh -v -t=5 ``` This command runs test number 5 in verbose mode. @@ -139,7 +139,7 @@ By following these guidelines, you can create a robust test suite that helps mai The project includes scripts for recording and replaying test scenarios: - `record_test.sh`: Records a single test case. -- `recordtests.sh`: Records multiple test cases. +- `record_tests.sh`: Records multiple test cases. #### Recording a Single Test @@ -156,13 +156,13 @@ This script will prompt you to enter test commands, a description, and any neces To record multiple tests: 1. Navigate to the `tests/` directory. -2. Run the `recordtests.sh` script: +2. Run the `record_tests.sh` script: ```bash -./recordtests.sh [options] +./record_tests.sh [options] ``` -The `recordtests.sh` script supports the following options: +The `record_tests.sh` script supports the following options: - `-q`: Quiet mode. Reduces output verbosity. - `-v`: Validate mode. Performs additional validation checks. @@ -171,21 +171,21 @@ The `recordtests.sh` script supports the following options: Example usage: ```bash -./recordtests.sh -v -t=10 +./record_tests.sh -v -t=10 ``` This command records test number 5 in quiet and validate mode. This command will record test number 10 with validation enabled. -When running `recordtests.sh`: +When running `record_tests.sh`: 1. The script will prompt you to enter test commands for each test case. 2. After entering the commands, you'll be asked to provide a brief description of the test. 3. You can specify any necessary arguments for the test. 4. The script will generate a new `.test` file for each recorded test in the `tests/` directory. -Using `recordtests.sh` is particularly useful when you need to create multiple related tests or when you want to quickly generate a series of test cases for a new feature or bug fix. +Using `record_tests.sh` is particularly useful when you need to create multiple related tests or when you want to quickly generate a series of test cases for a new feature or bug fix. ### Exporting and Importing Tests diff --git a/tests/create_test.sh b/tests/create_test.sh index 981286f3..a88c6913 100755 --- a/tests/create_test.sh +++ b/tests/create_test.sh @@ -1,6 +1,6 @@ #!/bin/bash -HELIOS="../HeliosCLI/helios" +HELIOS="./output/helios_cli" OUTPUT_FILE="recorded_input.txt" # Color definitions @@ -61,7 +61,8 @@ function insert_w10_w100() { echo "300w${output_string}300wq" } -TESTDIR=tests +# Test directory relative to CWD (HeliosCLI) +TESTDIR=../tests/tests mkdir -p $TESTDIR @@ -142,14 +143,14 @@ while true; do # replace spaces with underscores TEST_NAME="${TEST_NAME// /_}" - # cd to test dir - cd $TESTDIR - - # Create the test file with an incremented prefix number + # Determine test file path relative to CWD (HeliosCLI) PREFIX=0 MAX_PREFIX=0 - for file in [0-9][0-9][0-9][0-9]*.test; do + for file in $TESTDIR/[0-9][0-9][0-9][0-9]*.test; do + # Check if file exists + [ -e "$file" ] || continue PREFIX_NUM="${file%%_*}" + PREFIX_NUM="${PREFIX_NUM##*/}" if [[ "$PREFIX_NUM" =~ ^[0-9]+$ ]]; then if ((10#$PREFIX_NUM > 10#$MAX_PREFIX)); then MAX_PREFIX=$PREFIX_NUM @@ -160,7 +161,7 @@ while true; do if [ "$TODO" != "" ]; then NEXT_PREFIX=$TODO fi - TEST_FILE="$(printf "%04d" $NEXT_PREFIX)_${TEST_NAME}.test" + TEST_FILE="$TESTDIR/$(printf "%04d" $NEXT_PREFIX)_${TEST_NAME}.test" # Write the test information to the test file echo "Input=${NEW_INPUT}" > "$TEST_FILE" @@ -168,15 +169,12 @@ while true; do echo "Args=${ARGS}" >> "$TEST_FILE" echo "--------------------------------------------------------------------------------" >> "$TEST_FILE" - # generate the history for the test and append it to the test file - echo "${NEW_INPUT}" | ../$HELIOS $ARGS --hex --no-timestep >> "$TEST_FILE" + # generate the history for the test and append it to the test file (run Helios from CWD: HeliosCLI) + echo "${NEW_INPUT}" | $HELIOS $ARGS --hex --no-timestep >> "$TEST_FILE" # strip any \r in case this was run on windows sed -i 's/\r//g' $TEST_FILE - # cd back - cd - - # done echo "Test file created: ${TEST_FILE}" diff --git a/tests/export_tests.sh b/tests/export_tests.sh index 14f85c1b..d87e690c 100755 --- a/tests/export_tests.sh +++ b/tests/export_tests.sh @@ -1,9 +1,9 @@ #!/bin/bash -# Directory containing test files -TEST_DIR="./tests" +# Directory containing test files relative to CWD (HeliosCLI) +TEST_DIR="../tests/tests" -# Output CSV file +# Output CSV file relative to CWD (HeliosCLI) OUTPUT_CSV="output.csv" # Write header to the CSV file diff --git a/tests/import_tests.sh b/tests/import_tests.sh index fc51a9ac..863e1f4f 100755 --- a/tests/import_tests.sh +++ b/tests/import_tests.sh @@ -1,4 +1,8 @@ #!/bin/bash + +# Helios path relative to HeliosCLI CWD +HELIOS="./output/helios_cli" + parse_csv() { tail -n +2 "$1" | while IFS=, read -r input brief file_name do @@ -19,30 +23,29 @@ create_test() { # Format the file name with prefix and replace spaces with underscores local test_file="$(printf "%04d" $next_prefix)_${file_name// /_}.test" - # Create test file - cd $TESTDIR - - echo "Input=${input}" > "$test_file" - echo "Brief=${brief}" >> "$test_file" - echo "Args=" - echo "--------------------------------------------------------------------------------" >> "$test_file" + # Create test file inside TESTDIR (relative to CWD: HeliosCLI) + # No need to cd, paths are relative + echo "Input=${input}" > "$TESTDIR/$test_file" + echo "Brief=${brief}" >> "$TESTDIR/$test_file" + echo "Args=" >> "$TESTDIR/$test_file" + echo "--------------------------------------------------------------------------------" >> "$TESTDIR/$test_file" - # Append history to the test file - echo "$input" | $HELIOS --hex --no-timestep >> "$test_file" + # Append history to the test file (run Helios from CWD: HeliosCLI) + echo "$input" | $HELIOS --hex --no-timestep >> "$TESTDIR/$test_file" # Strip any \r in case this was run on windows - sed -i 's/\r//g' $test_file + sed -i 's/\r//g' "$TESTDIR/$test_file" - # Return to previous directory - cd - - - echo "Test file created: ${test_file}" + echo "Test file created: $TESTDIR/${test_file}" } # Function to get the next available prefix number get_next_prefix() { local max_prefix=0 + # Look for files in TESTDIR (relative to CWD: HeliosCLI) for file in $TESTDIR/[0-9][0-9][0-9][0-9]*.test; do + # Check if file exists to avoid errors on empty dir + [ -e "$file" ] || continue local prefix_num="${file%%_*}" prefix_num="${prefix_num##*/}" prefix_num="${prefix_num%%.*}" @@ -63,13 +66,10 @@ fi CSV_FILE="$1" -# Set the directory for test files -TESTDIR="tests" +# Set the directory for test files relative to CWD (HeliosCLI) +TESTDIR="../tests/tests" mkdir -p $TESTDIR -# Helios command path -HELIOS="../HeliosCLI/helios" - # Check if the CSV file exists if [ ! -f "$CSV_FILE" ]; then echo "CSV file not found: $CSV_FILE" diff --git a/tests/record_test.sh b/tests/record_test.sh index 3d5a7c19..b5479461 100755 --- a/tests/record_test.sh +++ b/tests/record_test.sh @@ -1,6 +1,7 @@ #!/bin/bash -HELIOS="../HeliosCLI/helios" +# Helios path relative to HeliosCLI CWD +HELIOS="./output/helios_cli" FILE=$1 VALIDATE=$2 @@ -24,12 +25,15 @@ fi INPUT="$(grep "Input=" $FILE | cut -d= -f2 | tr -d '\n' | tr -d '\r')" BRIEF="$(grep "Brief=" $FILE | cut -d= -f2 | tr -d '\n' | tr -d '\r')" ARGS="$(grep "Args=" $FILE | cut -d= -f2 | tr -d '\n' | tr -d '\r')" -TESTNUM="$(echo $FILE | cut -d/ -f3 | cut -d_ -f1 | cut -d/ -f2)" -TESTNUM=$((10#$TESTNUM)) +# Extract Test number correctly from basename +TESTNUM_FILENAME_PART=$(basename "$FILE") +TESTNUM_PREFIX=$(echo "$TESTNUM_FILENAME_PART" | cut -d_ -f1) +TESTNUM=$((10#$TESTNUM_PREFIX)) if [ "$QUIET" -eq 0 ]; then echo -e -n "\e[31mRecording test ($TESTCOUNT/$NUMFILES) \e[33m[\e[97m$BRIEF\e[33m] \e[33m[\e[97m$ARGS\e[33m]...\e[0m" fi +# Temp file path relative to CWD (HeliosCLI) TEMP_FILE="tmp/${FILE}.out" # Append the output of the $HELIOS command to the temp file # NOTE: When recording the tests we don't use valgrind because @@ -40,10 +44,11 @@ echo "Brief=${BRIEF}" >> "$TEMP_FILE" echo "Args=${ARGS}" >> "$TEMP_FILE" echo "--------------------------------------------------------------------------------" >> "$TEMP_FILE" -# ensure there is no existing storage file +# ensure there is no existing storage file (in CWD: HeliosCLI) rm -f Helios.storage # strip any \r in case this was run on windows +# Run Helios from CWD (HeliosCLI) $HELIOS $ARGS --no-timestep --hex <<< $INPUT >> $TEMP_FILE sed -i 's/\r//g' $TEMP_FILE @@ -55,6 +60,7 @@ else echo -n "." fi if [ "$VALIDATE" -eq 1 ]; then + # Run Helios from CWD (HeliosCLI) for validation $HELIOS $ARGS --no-timestep --color <<< $INPUT echo -e "\e[31mRecorded \e[33m[\e[97m$BRIEF\e[33m] \e[33m[\e[97m$ARGS\e[33m]\e[0m" echo -en "${YELLOW}Is this correct? (Y/n):${WHITE} " diff --git a/tests/recordtests.sh b/tests/record_tests.sh similarity index 82% rename from tests/recordtests.sh rename to tests/record_tests.sh index d9fbf8ad..cf9f469f 100755 --- a/tests/recordtests.sh +++ b/tests/record_tests.sh @@ -1,7 +1,7 @@ #!/bin/bash VALGRIND="valgrind --quiet --leak-check=full --show-leak-kinds=all" -HELIOS="../HeliosCLI/helios" +HELIOS="./output/helios_cli" VALIDATE=0 QUIET=0 @@ -42,16 +42,17 @@ fi echo -e "\e[32mSuccess\e[0m" function record_tests() { - # Directory where this script is located - SCRIPT_DIR="$(dirname "$0")" + # Directory where this script is located relative to CWD (HeliosCLI) + SCRIPT_DIR="../tests" - # Full path to the tests directory + # Full path to the tests directory relative to CWD (HeliosCLI) PROJECT="$SCRIPT_DIR/tests" FILES=() - rm -rf "$SCRIPT_DIR"/tmp/$PROJECT - mkdir -p "$SCRIPT_DIR"/tmp/$PROJECT + # Temp dir relative to CWD (HeliosCLI) + rm -rf tmp/$PROJECT + mkdir -p tmp/$PROJECT if [ "$TODO" != "" ]; then @@ -74,7 +75,7 @@ function record_tests() { TESTCOUNT=0 for FILE in "${FILES[@]}"; do - # Call the record_test.sh using its relative path + # Call the record_test.sh using its relative path from CWD (HeliosCLI) "$SCRIPT_DIR"/record_test.sh "$FILE" $VALIDATE $TESTCOUNT "$NUMFILES" $QUIET TESTCOUNT=$((TESTCOUNT + 1)) done diff --git a/tests/runtests.sh b/tests/run_tests.sh similarity index 88% rename from tests/runtests.sh rename to tests/run_tests.sh index 62443312..457a450b 100755 --- a/tests/runtests.sh +++ b/tests/run_tests.sh @@ -1,7 +1,8 @@ #!/bin/bash VALGRIND= -HELIOS="../HeliosCLI/helios" +# Path relative to HeliosCLI CWD +HELIOS="./output/helios_cli" DIFF="diff --strip-trailing-cr" # select the target repo to create a test for @@ -34,7 +35,8 @@ do done function run_tests() { - PROJECT="tests" + # Path relative to HeliosCLI CWD + PROJECT="../tests/tests" ALLSUCCES=1 @@ -66,7 +68,7 @@ function run_tests() { echo -e "\e[33m== [\e[97mRunning $NUMFILES Helios Integration Tests\e[33m] ==\e[0m" - # clear tmp folder + # clear tmp folder relative to HeliosCLI CWD rm -rf tmp/$PROJECT mkdir -p tmp/$PROJECT @@ -76,8 +78,10 @@ function run_tests() { INPUT="$(grep "Input=" $FILE | cut -d= -f2 | tr -d '\n' | tr -d '\r')" BRIEF="$(grep "Brief=" $FILE | cut -d= -f2 | tr -d '\n' | tr -d '\r')" ARGS="$(grep "Args=" $FILE | cut -d= -f2 | tr -d '\n' | tr -d '\r')" - TESTNUM="$(echo $FILE | cut -d/ -f2 | cut -d_ -f1 | cut -d/ -f2)" - TESTNUM=$((10#$TESTNUM)) + # Extract Test number correctly from basename + TESTNUM_FILENAME_PART=$(basename "$FILE") + TESTNUM_PREFIX=$(echo "$TESTNUM_FILENAME_PART" | cut -d_ -f1) + TESTNUM=$((10#$TESTNUM_PREFIX)) # Use the extracted prefix TESTCOUNT=$((TESTCOUNT + 1)) echo -e -n "\e[33mRunning test ($TESTCOUNT/$NUMFILES) [\e[97m$BRIEF\e[33m] " if [ "$ARGS" != "" ]; then @@ -104,9 +108,9 @@ function run_tests() { echo "Test: $TESTNUM" echo "-----------------------------" fi - # ensure there is no leftover storage file + # ensure there is no leftover storage file (in HeliosCLI CWD) rm -f Helios.storage - # now run the test + # now run the test (from HeliosCLI CWD) $VALGRIND $HELIOS $ARGS --no-timestep --hex <<< $INPUT &> $OUTPUT # and diff the result $DIFF --brief $EXPECTED $OUTPUT &> $DIFFOUT