Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ cmake_install.cmake
Makefile
build
tools
# Exception: include the root Makefile
!Makefile

# Resulting binary files
*.a
Expand Down Expand Up @@ -55,3 +57,12 @@ src/arm-none-eabi
node_modules
package.json
package-lock.json

# Local simulation and container virtualization artifacts
build_lv_sim/
InfiniSim/
.podman/
.containers/

# Local duplicate helper script (tracked copy lives in tools/)
run-infinisim-podman.sh
104 changes: 104 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
.PHONY: check-runtime ensure-firmware-image build build-infinisim run-infinisim clean help

# Default target
.DEFAULT_GOAL := build

# Build directories
BUILD_DIR ?= build
INFINISIM_DIR ?= build_lv_sim/InfiniSim
INFINISIM_BUILD_DIR ?= $(INFINISIM_DIR)/build

# Container configuration
CONTAINER_RUNTIME ?= $(shell if command -v podman >/dev/null 2>&1; then echo podman; elif command -v docker >/dev/null 2>&1; then echo docker; fi)
CONTAINER_VOLUME_SUFFIX := $(shell if [ "$(CONTAINER_RUNTIME)" = "podman" ]; then echo ":Z"; fi)
FIRMWARE_IMAGE_NAME ?= infinitime-build
INFINISIM_IMAGE_NAME ?= infinisim-build
REBUILD_IMAGE ?= 0

check-runtime:
@if [ -z "$(CONTAINER_RUNTIME)" ]; then \
echo "Error: neither podman nor docker is installed." >&2; \
echo "Install one container runtime and try again." >&2; \
echo "Examples:" >&2; \
echo " Fedora: sudo dnf install podman" >&2; \
echo " Debian/Ubuntu: sudo apt install podman" >&2; \
echo " Docker alternative: https://docs.docker.com/engine/install/" >&2; \
echo "Then verify with: podman --version or docker --version" >&2; \
exit 1; \
fi

ensure-firmware-image: check-runtime
@if [ "$(REBUILD_IMAGE)" = "1" ] || ! $(CONTAINER_RUNTIME) image inspect "$(FIRMWARE_IMAGE_NAME)" >/dev/null 2>&1; then \
echo "[1/2] Building firmware container image: $(FIRMWARE_IMAGE_NAME)"; \
$(CONTAINER_RUNTIME) build -t "$(FIRMWARE_IMAGE_NAME)" -f docker/Dockerfile docker; \
else \
echo "[1/2] Firmware container image already exists: $(FIRMWARE_IMAGE_NAME)"; \
fi

help:
@echo "InfiniTime Build System"
@echo "======================="
@echo ""
@echo "Targets:"
@echo " make build Build the InfiniTime firmware in container (default)"
@echo " make build-infinisim Build InfiniSim simulator in container"
@echo " make run-infinisim Run the InfiniSim simulator"
@echo " make clean Clean build directories"
@echo ""
@echo "Environment Variables:"
@echo " CONTAINER_RUNTIME Container runtime (auto: podman, fallback: docker)"
@echo " BUILD_DIR Firmware build directory (default: build)"
@echo " INFINISIM_DIR InfiniSim source directory (default: build_lv_sim/InfiniSim)"
@echo " INFINISIM_BUILD_DIR Simulator build directory (default: build_lv_sim/InfiniSim/build)"
@echo " FIRMWARE_IMAGE_NAME Firmware image name (default: infinitime-build)"
@echo " INFINISIM_IMAGE_NAME Simulator image name (default: infinisim-build)"
@echo " REBUILD_IMAGE Rebuild container image when set to 1"
@echo ""
@echo "Examples:"
@echo " make build # Build firmware in container"
@echo " make build REBUILD_IMAGE=1"
@echo " make build-infinisim # Build simulator in container"
@echo " make run-infinisim # Run simulator"

# Build firmware in container
build: ensure-firmware-image
@if [ -f "$(BUILD_DIR)/CMakeCache.txt" ]; then \
if ! grep -q '^CMAKE_HOME_DIRECTORY:INTERNAL=/sources$$' "$(BUILD_DIR)/CMakeCache.txt"; then \
echo "[prep] Removing incompatible CMake cache in $(BUILD_DIR) for container build"; \
rm -rf "$(BUILD_DIR)"; \
fi; \
fi
@echo "[2/2] Building firmware..."
@$(CONTAINER_RUNTIME) run --rm -it \
-v "$(CURDIR):/sources$(CONTAINER_VOLUME_SUFFIX)" \
-e "BUILD_DIR=/sources/$(BUILD_DIR)" \
-e "OUTPUT_DIR=/sources/$(BUILD_DIR)/output" \
"$(FIRMWARE_IMAGE_NAME)"

# Build InfiniSim simulator in container
build-infinisim: check-runtime
@echo "[1/3] Preparing InfiniSim build..."
@if [ ! -x "tools/run-infinisim-podman.sh" ]; then \
echo "Error: tools/run-infinisim-podman.sh is missing or not executable" >&2; \
exit 1; \
fi
@INFINISIM_DIR="$(INFINISIM_DIR)" CONTAINER_RUNTIME="$(CONTAINER_RUNTIME)" IMAGE_NAME="$(INFINISIM_IMAGE_NAME)" REBUILD_IMAGE="$(REBUILD_IMAGE)" tools/run-infinisim-podman.sh --no-run

# Run the InfiniSim simulator
run-infinisim: check-runtime
@if [ ! -x "tools/run-infinisim-podman.sh" ]; then \
echo "Error: tools/run-infinisim-podman.sh is missing or not executable" >&2; \
exit 1; \
fi
@echo "[3/3] Starting simulator..."
@INFINISIM_DIR="$(INFINISIM_DIR)" CONTAINER_RUNTIME="$(CONTAINER_RUNTIME)" IMAGE_NAME="$(INFINISIM_IMAGE_NAME)" REBUILD_IMAGE="$(REBUILD_IMAGE)" tools/run-infinisim-podman.sh

# Clean build directories
clean:
@echo "Cleaning build directories..."
@rm -rf $(BUILD_DIR)
@rm -rf $(INFINISIM_BUILD_DIR)
@echo "Clean complete"

# Phony targets
.PHONY: check-runtime ensure-firmware-image build build-infinisim run-infinisim clean help
166 changes: 166 additions & 0 deletions tools/run-infinisim-podman.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ -f "${SCRIPT_DIR}/../CMakeLists.txt" && -d "${SCRIPT_DIR}/../src" ]]; then
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
elif [[ -f "${SCRIPT_DIR}/CMakeLists.txt" && -d "${SCRIPT_DIR}/src" ]]; then
ROOT_DIR="${SCRIPT_DIR}"
else
echo "Error: could not locate repository root." >&2
exit 1
fi
SIM_DIR="${INFINISIM_DIR:-${ROOT_DIR}/build_lv_sim/InfiniSim}"
if [[ "${SIM_DIR}" != /* ]]; then
SIM_DIR="${ROOT_DIR}/${SIM_DIR}"
fi
IMAGE_NAME="${IMAGE_NAME:-infinisim-build}"
CONTAINER_RUNTIME="${CONTAINER_RUNTIME:-}"
BUILD_DIR="${BUILD_DIR:-build}"
INFINISIM_REPO="${INFINISIM_REPO:-https://github.com/InfiniTimeOrg/InfiniSim.git}"
INFINISIM_REF="${INFINISIM_REF:-main}"
UPDATE_INFINISIM="${UPDATE_INFINISIM:-0}"
REBUILD_IMAGE=0
RUN_BINARY=1
SIM_ARGS=()

usage() {
cat <<'EOF'
Usage: tools/run-infinisim-podman.sh [options] [-- <infinisim-args>]

Options:
--rebuild-image Rebuild Podman image without cache
--no-run Only build, do not execute ./build/infinisim
-h, --help Show this help

Environment variables:
IMAGE_NAME Podman image name (default: infinisim-build)
CONTAINER_RUNTIME Runtime to use (podman or docker, auto-detected if empty)
INFINISIM_DIR InfiniSim source directory (default: build_lv_sim/InfiniSim)
INFINISIM_REPO InfiniSim git repository URL
INFINISIM_REF InfiniSim git reference to clone (default: main)
UPDATE_INFINISIM Set to 1 to update existing clone to INFINISIM_REF
BUILD_DIR Build directory inside InfiniSim (default: build)

Examples:
tools/run-infinisim-podman.sh
tools/run-infinisim-podman.sh --rebuild-image
tools/run-infinisim-podman.sh -- --hide-status
EOF
}

while [[ $# -gt 0 ]]; do
case "$1" in
--rebuild-image)
REBUILD_IMAGE=1
shift
;;
--no-run)
RUN_BINARY=0
shift
;;
-h|--help)
usage
exit 0
;;
--)
shift
SIM_ARGS=("$@")
break
;;
*)
echo "Unknown option: $1" >&2
usage
exit 1
;;
esac
done

if [[ -z "${CONTAINER_RUNTIME}" ]]; then
if command -v podman >/dev/null 2>&1; then
CONTAINER_RUNTIME="podman"
elif command -v docker >/dev/null 2>&1; then
CONTAINER_RUNTIME="docker"
else
echo "Error: neither podman nor docker is installed or available in PATH." >&2
exit 1
fi
fi

if [[ ! -d "${SIM_DIR}" ]]; then
echo "[prep] InfiniSim source not found at ${SIM_DIR}; cloning ${INFINISIM_REF}"
mkdir -p "$(dirname "${SIM_DIR}")"
git clone --depth 1 --branch "${INFINISIM_REF}" "${INFINISIM_REPO}" "${SIM_DIR}"
fi

if [[ ! -d "${SIM_DIR}/.git" ]]; then
echo "Error: ${SIM_DIR} exists but is not a git checkout." >&2
exit 1
fi

if [[ "${UPDATE_INFINISIM}" == "1" ]]; then
echo "[prep] Updating InfiniSim checkout to ${INFINISIM_REF}"
git -C "${SIM_DIR}" fetch --depth 1 origin "${INFINISIM_REF}"
git -C "${SIM_DIR}" reset --hard FETCH_HEAD
fi

VOLUME_SUFFIX=""
if [[ "${CONTAINER_RUNTIME}" == "podman" ]]; then
VOLUME_SUFFIX=":Z"
fi

cd "${SIM_DIR}"

PATCHED_CMAKELISTS=0
cleanup() {
if [[ ${PATCHED_CMAKELISTS} -eq 1 && -f "${SIM_DIR}/CMakeLists.txt.copilot-backup" ]]; then
mv "${SIM_DIR}/CMakeLists.txt.copilot-backup" "${SIM_DIR}/CMakeLists.txt"
fi
}
trap cleanup EXIT

if [[ -f "${SIM_DIR}/CMakeLists.txt" ]] && [[ ! -f "${ROOT_DIR}/src/displayapp/localization/Localization.h" ]] && grep -q "displayapp/localization/Localization.h" "${SIM_DIR}/CMakeLists.txt"; then
echo "[prep] Detected incompatible localization entries in InfiniSim/CMakeLists.txt; patching for current branch"
cp "${SIM_DIR}/CMakeLists.txt" "${SIM_DIR}/CMakeLists.txt.copilot-backup"
sed -i \
-e '/displayapp\/localization\/Localization\.h/d' \
-e '/displayapp\/localization\/Localization\.cpp/d' \
"${SIM_DIR}/CMakeLists.txt"
PATCHED_CMAKELISTS=1
fi

echo "[1/4] Initializing submodules"
git submodule update --init --recursive

if [[ ${REBUILD_IMAGE} -eq 1 ]]; then
echo "[2/4] Rebuilding container image (no cache): ${IMAGE_NAME}"
"${CONTAINER_RUNTIME}" build --no-cache -t "${IMAGE_NAME}" -f .devcontainer/Dockerfile .
else
if ! "${CONTAINER_RUNTIME}" image inspect "${IMAGE_NAME}" >/dev/null 2>&1; then
echo "[2/4] Building container image: ${IMAGE_NAME}"
"${CONTAINER_RUNTIME}" build -t "${IMAGE_NAME}" -f .devcontainer/Dockerfile .
else
echo "[2/4] Container image already exists: ${IMAGE_NAME}"
fi
fi

echo "[3/4] Building InfiniSim in container"
"${CONTAINER_RUNTIME}" run --rm -it \
-v "${SIM_DIR}:/sources${VOLUME_SUFFIX}" \
-v "${ROOT_DIR}:/sources/InfiniTime${VOLUME_SUFFIX}" \
-e "BUILD_DIRECTORY=${BUILD_DIR}" \
-w /sources \
"${IMAGE_NAME}"

if [[ ${RUN_BINARY} -eq 1 ]]; then
BIN_PATH="${SIM_DIR}/${BUILD_DIR}/infinisim"
if [[ ! -x "${BIN_PATH}" ]]; then
echo "Error: binary not found at ${BIN_PATH}" >&2
exit 1
fi

echo "[4/4] Running simulator: ${BIN_PATH} ${SIM_ARGS[*]:-}"
"${BIN_PATH}" "${SIM_ARGS[@]}"
else
echo "[4/4] Build finished (execution skipped by --no-run)"
fi
Loading