# Configuration file for recipe commands

$(REPO_TAG): prefix $(FILESYSTEM_CONFIG) | $(FSTOOLS) $(FSTOOLS_TAG) $(CONTAINER_TAG)
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	export PATH="$(PREFIX_PATH):$$PATH" && \
	export COOKBOOK_HOST_SYSROOT="$(ROOT)/$(PREFIX_INSTALL)" && \
	$(REPO_BIN) cook $(COOKBOOK_OPTS) --with-package-deps
	mkdir -p $(BUILD)
	touch $@
endif

comma := ,

# List all recipes in a cook-tree fashion specified by the filesystem config
repo-tree: $(FSTOOLS_TAG) $(CONTAINER_TAG)
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	@$(REPO_BIN) cook-tree $(COOKBOOK_OPTS) --with-package-deps
endif

# List all recipes in a push-tree fashion specified by the filesystem config
image-tree: $(FSTOOLS_TAG) $(CONTAINER_TAG)
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	@$(REPO_BIN) push-tree $(COOKBOOK_OPTS)
endif

# Clean specific target to all recipes, similar to repo_clean but more specific
repo_clean_target: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) clean-target --all
endif

# Fetch all recipes source or binary from filesystem config
fetch: prefix $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	export PATH="$(PREFIX_PATH):$$PATH" && \
	export COOKBOOK_HOST_SYSROOT="$(ROOT)/$(PREFIX_INSTALL)" && \
	$(REPO_BIN) fetch $(COOKBOOK_OPTS) --with-package-deps
endif

# Unfetch and clean all recipes source or binary from filesystem config
unfetch: prefix $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) unfetch $(COOKBOOK_OPTS) --with-package-deps
endif

# Fetch Cargo dependencies for the cookbook tool (needed for REPO_OFFLINE=1 builds)
cargo-fetch: FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(HOST_CARGO) fetch --manifest-path Cargo.toml --locked
endif

# Find recipe for one or more targets separated by comma
find.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	@$(REPO_BIN) find $(foreach f,$(subst $(comma), ,$*),$(f))
endif

# Invoke clean for relibc in recipe and relibc in sysroot
c.relibc: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) clean relibc
	rm -rf $(PREFIX)/relibc-install $(PREFIX)/sysroot
	@echo "\033[1;36;49mSysroot cleaned\033[0m"
endif

# Invoke clean for one or more targets separated by comma
c.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) clean $(foreach f,$(subst $(comma), ,$*),$(f))
endif

# Invoke fetch for one or more targets separated by comma
f.%: prefix $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	export PATH="$(PREFIX_PATH):$$PATH" && \
	export COOKBOOK_HOST_SYSROOT="$(ROOT)/$(PREFIX_INSTALL)" && \
	$(REPO_BIN) fetch $(foreach f,$(subst $(comma), ,$*),$(f)) $(COOKBOOK_OPTS)
endif

# Invoke cook for one or more targets separated by comma
r.%: prefix $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	export PATH="$(PREFIX_PATH):$$PATH" && \
	export COOKBOOK_HOST_SYSROOT="$(ROOT)/$(PREFIX_INSTALL)" && \
	$(REPO_BIN) cook $(foreach f,$(subst $(comma), ,$*),$(f)) $(COOKBOOK_OPTS)
endif

# Show what to cook
rt.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) cook-tree $(foreach f,$(subst $(comma), ,$*),$(f)) $(COOKBOOK_OPTS)
endif

MOUNTED_TAG=$(MOUNT_DIR)~

# Push compiled package into existing image
# DO NOT RUN THIS WHILE QEMU ALIVE, THE DISK MIGHT CORRUPT IN DOING SO
p.%: $(FSTOOLS_TAG) FORCE
ifeq ($(ALLOW_FSTOOLS),1)
	@rm -f $(MOUNTED_TAG)
	@if [ ! -d "$(MOUNT_DIR)" ]; then \
		$(MAKE) mount; \
		touch $(MOUNTED_TAG); \
	fi
endif
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@ ALLOW_FSTOOLS=$(FSTOOLS_IN_PODMAN)
else
	$(REPO_BIN) push $(foreach f,$(subst $(comma), ,$*),$(f)) "--sysroot=$(MOUNT_DIR)" $(COOKBOOK_OPTS)
endif
ifeq ($(ALLOW_FSTOOLS),1)
	@if [ -f $(MOUNTED_TAG) ]; then \
		$(MAKE) unmount && rm -f $(MOUNTED_TAG); \
	else echo "\033[0;33;49mNot unmounting by ourself, don't forget to do it\033[0m"; \
	fi
endif

# Show what to push
pt.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) push-tree $(foreach f,$(subst $(comma), ,$*),$(f)) $(COOKBOOK_OPTS)
endif

# Push all recipes specified by the filesystem config
push: $(FSTOOLS_TAG) FORCE
ifeq ($(ALLOW_FSTOOLS),1)
	@rm -f $(MOUNTED_TAG)
	@if [ ! -d "$(MOUNT_DIR)" ]; then \
		$(MAKE) mount; \
		touch $(MOUNTED_TAG); \
	fi
endif
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@ ALLOW_FSTOOLS=$(FSTOOLS_IN_PODMAN)
else
	$(REPO_BIN) push $(COOKBOOK_OPTS) --with-package-deps "--sysroot=$(MOUNT_DIR)"
endif
ifeq ($(ALLOW_FSTOOLS),1)
	@if [ -f $(MOUNTED_TAG) ]; then \
		$(MAKE) unmount && rm -f $(MOUNTED_TAG); \
	else echo "\033[1;33;49mNot unmounting by ourself, don't forget to do it\033[0m"; \
	fi
endif

# Rebuild and push all recipes specified by the filesystem config
rebuild-push: $(FSTOOLS_TAG) FORCE
	rm -f $(REPO_TAG)
	$(MAKE) repo
	$(MAKE) push

# Invoke unfetch for one or more targets separated by comma
u.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) unfetch $(foreach f,$(subst $(comma), ,$*),$(f))
endif

# Invoke clean, and rebuild for one of more targets separated by comma
cr.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(MAKE) c.$*
	$(MAKE) r.$*
endif

# Invoke unfetch, clean, and rebuild for one or more targets separated by comma
ucr.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(MAKE) u.$*
	$(MAKE) cr.$*
endif

# Invoke unfetch and clean for one or more targets separated by comma
uc.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(MAKE) u.$*
	$(MAKE) c.$*
endif

# Invoke unfetch, clean and fetch for one or more targets separated by comma
ucf.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(MAKE) uc.$*
	$(MAKE) f.$*
endif

# Invoke rebuild and push for one of more targets separated by comma
# Don't use podman here, as the p target cannot mount inside podman
rp.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) r.$*,--with-package-deps
	$(MAKE) p.$*

# Invoke clean, rebuild and push for one of more targets separated by comma
crp.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) cr.$*,--with-package-deps
	$(MAKE) p.$*

# Invoke unfetch. clean, rebuild and push for one of more targets separated by comma
ucrp.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) ucr.$*,--with-package-deps
	$(MAKE) p.$*

ifeq ($(HOSTED_REDOX),1)
DESTDIR?=/

# Install all recipes specified by the filesystem config
install:
	$(REPO_BIN) push $(COOKBOOK_OPTS) --with-package-deps "--sysroot=$(DESTDIR)"

# Rebuild and install all recipes specified by the filesystem config
rebuild-install: $(FSTOOLS_TAG) FORCE
	rm -f $(REPO_TAG)
	$(MAKE) repo
	$(MAKE) install

i.%: $(FSTOOLS_TAG) FORCE
	$(REPO_BIN) push $(COOKBOOK_OPTS) --with-package-deps "--sysroot=$(DESTDIR)"

# Invoke rebuild and install for one of more targets separated by comma
ri.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) r.$*,--with-package-deps
	$(MAKE) i.$*

# Invoke clean, rebuild and install for one of more targets separated by comma
cri.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) cr.$*,--with-package-deps
	$(MAKE) i.$*

# Invoke unfetch. clean, rebuild and install for one of more targets separated by comma
ucri.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) ucr.$*,--with-package-deps
	$(MAKE) i.$*
endif

# Set recipe rule to "binary" then invoke clean
bc.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) change-rule --set-rule=binary $(foreach f,$(subst $(comma), ,$*),$(f)) --with-package-deps
endif

# Set recipe rule to "source" then invoke clean
sc.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) change-rule --set-rule=source $(foreach f,$(subst $(comma), ,$*),$(f)) --with-package-deps
endif

# Set specific recipe rule to "local" then invoke clean
lc.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) change-rule-local --set-rule=local $(foreach f,$(subst $(comma), ,$*),$(f))
endif

# Set specific recipe rule to "ignore" then invoke clean
nc.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) change-rule-local --set-rule=ignore $(foreach f,$(subst $(comma), ,$*),$(f))
endif

# Reset recipe rule then invoke clean
cc.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) change-rule --unset $(foreach f,$(subst $(comma), ,$*),$(f)) --with-package-deps
endif

# Set recipe rule to "binary" then invoke clean and rebuild
bcr.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) bc.$*
	$(MAKE) r.$*,--with-package-deps

# Set recipe rule to "source" then invoke clean and rebuild
scr.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) sc.$*
	$(MAKE) r.$*,--with-package-deps

# Set specific recipe rule to "local" then invoke clean and rebuild
lcr.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) lc.$*
	$(MAKE) r.$*

# Set specific recipe rule to "ignore" then invoke clean and rebuild
ncr.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) nc.$*
	$(MAKE) r.$*

# Set recipe rule to "binary" then invoke clean, rebuild and push
bcrp.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) bcr.$*
	$(MAKE) p.$*

# Set recipe rule to "source" then invoke clean, rebuild and push
scrp.%: $(FSTOOLS_TAG) FORCE
	$(MAKE) scr.$*
	$(MAKE) p.$*

# Save current git rev for next recipe fetch, locking git recipes frozen in time
repo-lock: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) capture-rev $(COOKBOOK_OPTS) --with-package-deps
endif

# Undo repo-lock, allowing git recipes to get updated by next recipe fetch
repo-unlock: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
else
	$(REPO_BIN) capture-rev $(COOKBOOK_OPTS) --unset --with-package-deps
endif

# Like repo-lock, but also checking out the specified git rev.
# Revert this operation by "git checkout master" "make pull" then "make repo-unlock".
# Will not work if rolling back to a commit before 2026.
repo-rollback.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	$(PODMAN_RUN) make $@
# have to be done otherwise podman will rebuild
	touch $(CONTAINER_TAG)
else
	git checkout $*
	$(REPO_BIN) capture-rev $(COOKBOOK_OPTS) --rollback --with-package-deps
endif
# have to be done otherwise cookbook will rebuild
	touch $(FSTOOLS_TAG)

export DEBUG_BIN?=

# Debug a statically linked program with gdbgui, for example: debug.drivers-initfs DEBUG_BIN=pcid
# Enable debug symbols with `REPO_DEBUG=1 make cr.recipe rebuild`, make sure `file` outputs "debug_info, not stripped"
# Open http://localhost:5000/dashboard, start QEMU with `make qemu kvm=no QEMU_SMP=1 gdb=yes` before opening a session
# Experimental, may not work if ARCH is different with what host is running
debug.%: $(FSTOOLS_TAG) FORCE
ifeq ($(PODMAN_BUILD),1)
	@cd $(shell make find.$* | grep ^recipes) && \
		export RECIPE_STAGE=target/$(TARGET)/stage && \
		export BIN_PATH=$$(find $$RECIPE_STAGE -type f -name "$(DEBUG_BIN)" -or -type f -name "$*") && \
		file $$BIN_PATH 2> /dev/null || ( echo "Binary is not found, please set DEBUG_BIN" && exit 1 ) && \
		echo "Opening gdbgui for debugging $* with binary '$$BIN_PATH'" && echo "----------" && \
		podman build -t redox-kernel-debug - < $(ROOT)/podman/redox-gdb-containerfile > /dev/null && \
		podman run --rm -p 5000:5000 -it --name redox-gdb \
		-v "./$$BIN_PATH:/binary" \
		-v "./source:/source" -w "/source" \
		redox-kernel-debug --gdb-cmd "gdb -ex 'set confirm off' \
			-ex 'add-symbol-file /binary' \
			-ex 'target remote host.containers.internal:1234'"
else
	@cd $(shell make find.$* | grep ^recipes) && \
		export RECIPE_STAGE=target/$(TARGET)/stage && \
		export BIN_PATH=$$(find $$RECIPE_STAGE -type f -name "$(DEBUG_BIN)" -or -type f -name "$*") && \
		file $$BIN_PATH 2> /dev/null || ( echo "Binary is not found, please set DEBUG_BIN" && exit 1 ) && \
		echo "Opening gdbgui for debugging $* with binary '$$BIN_PATH'" && echo "----------" && \
		gdbgui.pex --gdb-cmd "gdb -ex 'set confirm off' \
			-ex 'add-symbol-file $$BIN_PATH' \
			-ex 'target remote localhost:1234'"
endif
