NULL= EMPTY := SPACE := $(EMPTY) $(EMPTY) COMMA := , ESCAPEDSPACE := \$(SPACE) ESCAPEDSPACE_REPLACEMENT := @@SPACE@@ # This is useful to handle space in forech rules handle-escaped-space = $(subst $(ESCAPEDSPACE),$(ESCAPEDSPACE_REPLACEMENT),$1) apply-escaped-space = $(subst $(ESCAPEDSPACE_REPLACEMENT),$(SPACE),$1) HOST_ARCH:=$(shell arch) ARCHES := x86_64 export VM=0 OSBUILD_MPP=osbuild-mpp DEFINES= DEFINES_ARGS:=$(foreach def,$(call handle-escaped-space,$(DEFINES)),-D '$(call apply-escaped-space,$(def))') MPP_ARGS= export OSBUILD_ARGS= BUILDDIR=_build export STOREDIR=$(BUILDDIR)/osbuild_store export OUTPUTDIR=$(BUILDDIR)/image_output IMAGEDIR= DISTROS := $(basename $(basename $(notdir f,$(wildcard distro/*.ipp.yml)))) MANIFESTS := $(wildcard images/*.mpp.yml) $(foreach DIR,$(IMAGEDIR),$(wildcard $(DIR)/*)) EXTRA_MPP_ARGS= # For internal use ifdef OSTREE_REPO EXTRA_MPP_ARGS +=-D ostree_parent_refs='$(shell tools/ot-refs $(OSTREE_REPO))' endif export CHECKPOINTS=build IMAGETYPES := regular ostree FORMATS := img qcow2 oci.tar repo rootfs ext4 tar COMMON_TARGETS := qemu HOST_TARGETS := $(COMMON_TARGETS) $($(HOST_ARCH)_TARGETS) ALL_TARGETS := $(COMMON_TARGETS) $(foreach a,$(ARCHES), $($(a)_TARGETS)) manifest-get-name = $(basename $(basename $(notdir $1))) manifest-get-dir = $(notdir $(patsubst %/,%,$(dir $1))) image-name-noarch = $1-$3-$(call manifest-get-name,$2)-$4 image-name = $(call image-name-noarch,$1,$2,$3,$4).$5 # variable name for image type regular_IMAGETYPE := regular ostree_IMAGETYPE := ostree help: @echo @echo This makefile is a wrapper around osbuild-mpp and osbuild to easily build images @echo @echo To build a raw image, run \"make image.img\", or to build a qcow2 image, run \"make image.qcow2\". @echo This will build any image from a file called \"image.mpp.yml\" in the \"images\" subdirectory. You can @echo pass IMAGEDIR=/some/other/path to make also to pick up manifests from an external directory. @echo @echo For example, to build a minimal qcow2 image with ostree support targeting qemu, run: @echo ' make cs9-qemu-minimal-ostree.$(HOST_ARCH).qcow2' @echo @echo Other extensions are also supported: @echo \ \* .repo: Generate a repo with an ostree commit \(only works for ostree targets\) @echo \ \* .rootfs: Generate a directory with the rootfs content @echo \ \* .tar: Generate a tar file with the rootfs content @echo \ \* .ext4: Generate an ext4 filesystem with the rootfs content \(size from \"image_size\"\) @echo \ \* oci.tar: Generate an oci container image with the rootfs content @echo @echo You can pass variable declarations to osbuild-mpp with the DEFINES make variable. @echo Multiple defines are separated by space, if you need a space inside a value escape it using \"\\ \". @echo For example, to add extra rpms to a minimal regular image, use: @echo " make cs9-qemu-minimal-regular.$(HOST_ARCH).qcow2 DEFINES='extra_rpms=[\"gdb\",\"strace\"]'" @echo @echo To easily run the image with qemu, you can use the included runvm tool, like: @echo \ \ ./runvm cs9-qemu-minimal-regular.$(HOST_ARCH).qcow2 @echo @echo There are some additional targets: @echo \ \ manifests: generates resolved json manifests for all images without building them. @echo \ \ clean_caches: Removes intermediate image build artifacts \(that improve rebuild speed\) @echo \ \ clean_downloads: Removes files downloaded during image builds @echo \ \ clean: Run clean_caches and clean_downloads @echo \ \ osbuildvm-images: Build a image that can be used to build images inside a VM @echo @echo There are also some common conversion rules: @echo \ \ foo.ext4.simg will build foo.ext4 and then convert it with img2simg @echo \ \ foo.simg will build foo.img and then convert it with img2simg @echo \ \ foo.tar.gz will build $foo.tar and then gzip it @echo @echo "When building a custom variant of an image (say with an extra package) you can use a" @echo custom @suffix to change the name of the produced file. For example: @echo " make cs9-qemu-minimal-ostree@gdb.$(HOST_ARCH).qcow2 DEFINES='extra_rpms=[\"gdb\"]'" @echo @echo If you pass VM=1, then the images used from \"make osbuildvm-images\" will be used to do the @echo actual building. This means that you don\'t need sudo rights to run osbuild, and it means @echo architectures other than the current ones can be built. @echo @echo Available image targets \(for $(HOST_ARCH)\) are: @echo @$(foreach d, $(DISTROS), $(foreach m, $(MANIFESTS), $(foreach t, $(HOST_TARGETS), $(foreach i,$(IMAGETYPES), echo -e " " $(call image-name,$d,$m,$t,$i,$(HOST_ARCH)).[$(subst $(SPACE),$(COMMA),$(FORMATS))];)))) @echo # We pre-create all the toplevel dirs, so that they are owned by the user, not root (when created under sudo) .PHONY: $(BUILDDIR) $(BUILDDIR): @mkdir -p $(BUILDDIR) @mkdir -p $(STOREDIR)/{objects,refs,sources/org.osbuild.files,tmp} @mkdir -p $(OUTPUTDIR) # Template rule for producing osbuild json manifest from mpp yaml and image type # $1 == distro name # $2 == yaml manifest path # $3 == Target name # $4 == Image type # $5 == Arch define json-rule $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json: $2 $(BUILDDIR) $(OSBUILD_MPP) -I . -D image_type="\"$($4_IMAGETYPE)\"" -D arch=\"$5\" -D distro_name="\"$1\"" -D target="\"$3\"" $(DEFINES_ARGS) $(EXTRA_MPP_ARGS) $(MPP_ARGS) $$< $$@ .PHONY: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json endef $(foreach d, $(DISTROS), \ $(foreach m, $(MANIFESTS), \ $(foreach a,$(ARCHES), \ $(foreach t,$(COMMON_TARGETS) $($(a)_TARGETS), \ $(foreach i,$(IMAGETYPES), \ $(eval $(call json-rule,$d,$m,$t,$i,$a))))))) # Template rule for producing image from json manifest # $1 == distro name # $2 == Manifest path # $3 == Target # $4 == Image type # $5 == Arch # $6 == Export format (extension) define image-rule $(call image-name,$1,$2,$3,$4,$5).$6: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json @tools/runosbuild "$$@" "$$<" "$3" "$4" "$5" "$6" $(call image-name-noarch,$1,$2,$3,$4)@%.$5.$6: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json @tools/runosbuild "$$@" "$$<" "$3" "$4" "$5" "$6" endef $(foreach d, $(DISTROS), \ $(foreach m, $(MANIFESTS), \ $(foreach a,$(ARCHES), \ $(foreach t, $(COMMON_TARGETS) $($(a)_TARGETS), \ $(foreach f,$(FORMATS), \ $(foreach i,$(IMAGETYPES), \ $(eval $(call image-rule,$d,$m,$t,$i,$a,$f)))))))) # Rule to pre-generate all manifests manifests: $(foreach d, $(DISTROS),$(foreach m, $(MANIFESTS), $(foreach a,$(ARCHES), $(foreach t, $(COMMON_TARGETS) $($(a)_TARGETS), $(foreach i,$(IMAGETYPES), $(BUILDDIR)/$(call image-name,$d,$m,$t,$i,$a).json))))) define packages-rule .PHONY: packages-$(call manifest-get-name,$1).json packages-$(call manifest-get-name,$1).json: $1 osbuild-mpp $$< -D arch=\"x86_64\" - | jq -f tools/extract-rpms.jq > $$@.x86_64 osbuild-mpp $$< -D arch=\"aarch64\" - | jq -f tools/extract-rpms.jq > $$@.aarch64 echo 1 | jq --indent 4 -f tools/create-packagelist.jq --slurpfile x86_64 $$@.x86_64 --slurpfile aarch64 $$@.aarch64 > $$@ endef $(foreach m, $(MANIFESTS), $(eval $(call packages-rule,$m))) .PHONY: clean_downloads clean_downloads: sudo rm -rf _build/osbuild_store/sources/org.osbuild.files/* .PHONY: clean_caches clean_caches: sudo rm -rf $(STOREDIR)/refs/* sudo rm -rf $(STOREDIR)/refs_tars/* sudo rm -rf $(STOREDIR)/objects/* sudo rm -rf $(STOREDIR)/tmp/* sudo rm -rf $(STOREDIR)/image_output/* .PHONY: clean clean: clean_downloads clean_caches ifeq ($(VM), 1) VM_SUDO= VM_OSBUILD="osbuildvm/osbuildvm --arch=$(HOST_ARCH)" else VM_SUDO=sudo VM_OSBUILD=sudo osbuild endif .PHONY: osbuildvm-images osbuildvm-images: $(BUILDDIR) osbuild-mpp osbuildvm/osbuildvm.mpp.yml _build/osbuildvm-$(HOST_ARCH).json $(VM_OSBUILD) --store $(STOREDIR) --output-directory $(OUTPUTDIR) --export osbuildvm _build/osbuildvm-$(HOST_ARCH).json cp $(OUTPUTDIR)/osbuildvm/disk.qcow2 _build/osbuildvm-$(HOST_ARCH).img cp $(OUTPUTDIR)/osbuildvm/initramfs _build/osbuildvm-$(HOST_ARCH).initramfs cp $(OUTPUTDIR)/osbuildvm/vmlinuz _build/osbuildvm-$(HOST_ARCH).vmlinuz $(VM_SUDO) rm -rf $(OUTPUTDIR)/osbuildvm %.ext4.simg : %.ext4 img2simg $< $@ rm $< %.simg : %.img img2simg $< $@ rm $< %.tar.gz : %.tar gzip -f $<