buildroot/fs/common.mk

169 lines
6.0 KiB
Makefile
Raw Normal View History

#
# Macro that builds the needed Makefile target to create a root
# filesystem image.
#
# The following variable must be defined before calling this macro
#
# ROOTFS_$(FSTYPE)_CMD, the command that generates the root
# filesystem image. A single command is allowed. The filename of the
# filesystem image that it must generate is $$@.
#
# The following variables can optionaly be defined
#
# ROOTFS_$(FSTYPE)_DEPENDENCIES, the list of dependencies needed to
# build the root filesystem (usually host tools)
#
# ROOTFS_$(FSTYPE)_PRE_GEN_HOOKS, a list of hooks to call before
# generating the filesystem image
#
# ROOTFS_$(FSTYPE)_POST_GEN_HOOKS, a list of hooks to call after
# generating the filesystem image
#
# In terms of configuration option, this macro assumes that the
# BR2_TARGET_ROOTFS_$(FSTYPE) config option allows to enable/disable
# the generation of a filesystem image of a particular type. If
# the configuration options BR2_TARGET_ROOTFS_$(FSTYPE)_GZIP,
# BR2_TARGET_ROOTFS_$(FSTYPE)_BZIP2 or
# BR2_TARGET_ROOTFS_$(FSTYPE)_LZMA exist and are enabled, then the
# macro will automatically generate a compressed filesystem image.
FS_DIR = $(BUILD_DIR)/buildroot-fs
FULL_DEVICE_TABLE = $(FS_DIR)/device_table.txt
ROOTFS_DEVICE_TABLES = $(call qstrip,$(BR2_ROOTFS_DEVICE_TABLE) \
$(BR2_ROOTFS_STATIC_DEVICE_TABLE))
USERS_TABLE = $(FS_DIR)/users_table.txt
ROOTFS_USERS_TABLES = $(call qstrip,$(BR2_ROOTFS_USERS_TABLES))
ifeq ($(BR2_REPRODUCIBLE),y)
define ROOTFS_REPRODUCIBLE
find $(TARGET_DIR) -print0 | xargs -0 -r touch -hd @$(SOURCE_DATE_EPOCH)
endef
endif
ROOTFS_COMMON_DEPENDENCIES = \
host-fakeroot host-makedevs \
$(BR2_TAR_HOST_DEPENDENCY) \
$(if $(PACKAGES_USERS)$(ROOTFS_USERS_TABLES),host-mkpasswd)
fs: don't use an intermediate tarball Since 118534fe54b (fs: use a common tarball as base for the other filesystems), the filesystem creation is split in two steps, using an intermediate tarball to carry the generic, common finalisations to the per-filesystem finalisation and image creation. However, this intermediate tarball causes an issue with capabilities: they are entirely missing in the generated filesystems. Capabilities are stored in the extended attribute security.capability, which tar by default will not store/restore, unless explicitly told to, e.g. with --xattrs-include='*', which we don't pass. Now, passing this option when creating and extracting the intermediate tarball, both done under fakeroot, will cause fakeroot to report an invalid filetype for files with capabilities. mksquashfs would report such unknown files as a warning, while mkfs.ext2 would fail (with a similar error message), e.g.: File [...]/usr/sbin/getcap has unrecognised filetype 0, ignoring This is due to a poor interaction between tar and fakeroot; running as root the exact same commands we run under fakeroot, works as expected. Unfortunately, short of fixing fakeroot (which would first require understanding the problem in there), we don't have much options. The intermediate tarball was made to avoid redoing the same actions over and over again for each filesystem to build. However, most of the time, only one or two such filesystems would be enabled [0], and those actions are usually pretty lightweight. So, using an intermediate tarball does not provide a big optimisation. The main reason to introduce the intermediate tarball, however, is that it allows to postpone per-filesystem finalisations to be applied only for the corresponding filesystem, not for all of them. So, we get rid of the intermediate tarball, and simply move all of the code to run under fakeroot to the per-filesystem fakeroot script. Instead of extracting the intermediate tarball, we just rsync the original target/ directory, and apply the filesystem finalisations on that copy. The only thing still done in the rootfs-common step is to generate the intermediate files (users file, devices file) that are used in the fakeroot script. Fixes: https://bugs.busybox.net/show_bug.cgi?id=11216 Note: an alternate solution would have been to keep the intermediate tarball to keep most of the common finalisations, and move only the permissions to each filesystem, but that was getting a bit more complex and changed the ordering of permissions and post-fakeroot scripts. Once we bite the bullet of having some common finalisation done in each filesystem, it's easier to just move all of them. [0] Most probsably, users would enable the real filesystem to put on their device, plus the 'tar' filesystem, to be able to easily inspect the content on their development machine. Reported-by: Ricardo Martincoski <ricardo.martincoski@gmail.com> Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Ricardo Martincoski <ricardo.martincoski@gmail.com> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Cc: Arnout Vandecappelle <arnout@mind.be> Cc: Peter Korsgaard <peter@korsgaard.com> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
2018-11-13 01:33:11 +08:00
.PHONY: rootfs-common
rootfs-common: $(ROOTFS_COMMON_DEPENDENCIES) target-finalize
@$(call MESSAGE,"Generating root filesystems common tables")
rm -rf $(FS_DIR)
mkdir -p $(FS_DIR)
$(call PRINTF,$(PACKAGES_USERS)) >> $(USERS_TABLE)
ifneq ($(ROOTFS_USERS_TABLES),)
cat $(ROOTFS_USERS_TABLES) >> $(USERS_TABLE)
endif
ifneq ($(ROOTFS_DEVICE_TABLES),)
cat $(ROOTFS_DEVICE_TABLES) > $(FULL_DEVICE_TABLE)
ifeq ($(BR2_ROOTFS_DEVICE_CREATION_STATIC),y)
$(call PRINTF,$(PACKAGES_DEVICES_TABLE)) >> $(FULL_DEVICE_TABLE)
endif
endif
$(call PRINTF,$(PACKAGES_PERMISSIONS_TABLE)) >> $(FULL_DEVICE_TABLE)
rootfs-common-show-depends:
@echo $(ROOTFS_COMMON_DEPENDENCIES)
infra: consistently use double dollar signs inside inner-xxx-targets The inner-xxx-targets in the buildroot package infrastructures are evaluated using $(eval) which causes variable references to be a bit different than in regular make code. As we want most references to be expanded only at the time of the $(eval) we should not use standard references $(VAR) but rather use double dollar signs $$(VAR). This includes function references like $(call), $(subst), etc. The only exception is the reference to pkgdir/pkgname and numbered variables, which are parameters to the inner block: $(1), $(2), etc. This patch introduces consistent usage of double-dollar signs throughout the different inner-xxx-targets blocks. In some cases, this would potentially cause circular references, in particular when the value of HOST_FOO_VAR would be obtained from the corresponding FOO_VAR if HOST_FOO_VAR is not defined. In these cases, a test is added to check for a host package (the only case where such constructions are relevant; these are not circular). Benefits of these changes are: - behavior of variables is now again as expected. For example, setting $(2)_VERSION = virtual in pkg-virtual.mk will effectively work, while originally it would cause very odd results. - The output of 'make printvars' is now much more useful. This target shows the value of all variables, and the expression that led to that value. However, if the expression was coming from an inner-xxx-targets block, and was using single dollar signs, it would show in printvars as VAR = value (value) while if double dollar signs are used, it would effectively look like VAR = value (actual expression) as is intended. This improvement is for example effective for FOO_DL_VERSION, FOO_RAWNAME, FOO_SITE_METHOD and FOO_MAKE. The correctness of this patch has been verified using 'make printvars', 'make manual' and 'make legal-info' before and after applying this patch, and comparing the output. Insight-provided-by: Arnout Vandecappelle <arnout@mind.be> Signed-off-by: Thomas De Schampheleire <thomas.de.schampheleire@gmail.com> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2014-06-12 03:12:24 +08:00
# Since this function will be called from within an $(eval ...)
# all variable references except the arguments must be $$-quoted.
define inner-rootfs
ROOTFS_$(2)_IMAGE_NAME ?= rootfs.$(1)
ROOTFS_$(2)_FINAL_IMAGE_NAME = $$(strip $$(ROOTFS_$(2)_IMAGE_NAME))
ROOTFS_$(2)_DIR = $$(FS_DIR)/$(1)
ROOTFS_$(2)_TARGET_DIR = $$(ROOTFS_$(2)_DIR)/target
ROOTFS_$(2)_DEPENDENCIES += rootfs-common
ifeq ($$(BR2_TARGET_ROOTFS_$(2)_GZIP),y)
ROOTFS_$(2)_COMPRESS_EXT = .gz
ROOTFS_$(2)_COMPRESS_CMD = gzip -9 -c
endif
ifeq ($$(BR2_TARGET_ROOTFS_$(2)_BZIP2),y)
ROOTFS_$(2)_COMPRESS_EXT = .bz2
ROOTFS_$(2)_COMPRESS_CMD = bzip2 -9 -c
endif
ifeq ($$(BR2_TARGET_ROOTFS_$(2)_LZMA),y)
ROOTFS_$(2)_DEPENDENCIES += host-lzma
ROOTFS_$(2)_COMPRESS_EXT = .lzma
ROOTFS_$(2)_COMPRESS_CMD = $$(LZMA) -9 -c
endif
ifeq ($$(BR2_TARGET_ROOTFS_$(2)_LZ4),y)
ROOTFS_$(2)_DEPENDENCIES += host-lz4
ROOTFS_$(2)_COMPRESS_EXT = .lz4
ROOTFS_$(2)_COMPRESS_CMD = lz4 -l -9 -c
endif
ifeq ($$(BR2_TARGET_ROOTFS_$(2)_LZO),y)
ROOTFS_$(2)_DEPENDENCIES += host-lzop
ROOTFS_$(2)_COMPRESS_EXT = .lzo
ROOTFS_$(2)_COMPRESS_CMD = $$(LZOP) -9 -c
endif
ifeq ($$(BR2_TARGET_ROOTFS_$(2)_XZ),y)
ROOTFS_$(2)_DEPENDENCIES += host-xz
ROOTFS_$(2)_COMPRESS_EXT = .xz
ROOTFS_$(2)_COMPRESS_CMD = xz -9 -C crc32 -c
endif
$$(BINARIES_DIR)/$$(ROOTFS_$(2)_FINAL_IMAGE_NAME): ROOTFS=$(2)
$$(BINARIES_DIR)/$$(ROOTFS_$(2)_FINAL_IMAGE_NAME): FAKEROOT_SCRIPT=$$(ROOTFS_$(2)_DIR)/fakeroot
$$(BINARIES_DIR)/$$(ROOTFS_$(2)_FINAL_IMAGE_NAME): $$(ROOTFS_$(2)_DEPENDENCIES)
@$$(call MESSAGE,"Generating filesystem image $$(ROOTFS_$(2)_FINAL_IMAGE_NAME)")
mkdir -p $$(@D)
rm -rf $$(ROOTFS_$(2)_DIR)
mkdir -p $$(ROOTFS_$(2)_DIR)
fs: don't use an intermediate tarball Since 118534fe54b (fs: use a common tarball as base for the other filesystems), the filesystem creation is split in two steps, using an intermediate tarball to carry the generic, common finalisations to the per-filesystem finalisation and image creation. However, this intermediate tarball causes an issue with capabilities: they are entirely missing in the generated filesystems. Capabilities are stored in the extended attribute security.capability, which tar by default will not store/restore, unless explicitly told to, e.g. with --xattrs-include='*', which we don't pass. Now, passing this option when creating and extracting the intermediate tarball, both done under fakeroot, will cause fakeroot to report an invalid filetype for files with capabilities. mksquashfs would report such unknown files as a warning, while mkfs.ext2 would fail (with a similar error message), e.g.: File [...]/usr/sbin/getcap has unrecognised filetype 0, ignoring This is due to a poor interaction between tar and fakeroot; running as root the exact same commands we run under fakeroot, works as expected. Unfortunately, short of fixing fakeroot (which would first require understanding the problem in there), we don't have much options. The intermediate tarball was made to avoid redoing the same actions over and over again for each filesystem to build. However, most of the time, only one or two such filesystems would be enabled [0], and those actions are usually pretty lightweight. So, using an intermediate tarball does not provide a big optimisation. The main reason to introduce the intermediate tarball, however, is that it allows to postpone per-filesystem finalisations to be applied only for the corresponding filesystem, not for all of them. So, we get rid of the intermediate tarball, and simply move all of the code to run under fakeroot to the per-filesystem fakeroot script. Instead of extracting the intermediate tarball, we just rsync the original target/ directory, and apply the filesystem finalisations on that copy. The only thing still done in the rootfs-common step is to generate the intermediate files (users file, devices file) that are used in the fakeroot script. Fixes: https://bugs.busybox.net/show_bug.cgi?id=11216 Note: an alternate solution would have been to keep the intermediate tarball to keep most of the common finalisations, and move only the permissions to each filesystem, but that was getting a bit more complex and changed the ordering of permissions and post-fakeroot scripts. Once we bite the bullet of having some common finalisation done in each filesystem, it's easier to just move all of them. [0] Most probsably, users would enable the real filesystem to put on their device, plus the 'tar' filesystem, to be able to easily inspect the content on their development machine. Reported-by: Ricardo Martincoski <ricardo.martincoski@gmail.com> Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Ricardo Martincoski <ricardo.martincoski@gmail.com> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Cc: Arnout Vandecappelle <arnout@mind.be> Cc: Peter Korsgaard <peter@korsgaard.com> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
2018-11-13 01:33:11 +08:00
rsync -auH \
--exclude=/$$(notdir $$(TARGET_DIR_WARNING_FILE)) \
$$(BASE_TARGET_DIR)/ \
$$(TARGET_DIR)
echo '#!/bin/sh' > $$(FAKEROOT_SCRIPT)
echo "set -e" >> $$(FAKEROOT_SCRIPT)
fs: don't use an intermediate tarball Since 118534fe54b (fs: use a common tarball as base for the other filesystems), the filesystem creation is split in two steps, using an intermediate tarball to carry the generic, common finalisations to the per-filesystem finalisation and image creation. However, this intermediate tarball causes an issue with capabilities: they are entirely missing in the generated filesystems. Capabilities are stored in the extended attribute security.capability, which tar by default will not store/restore, unless explicitly told to, e.g. with --xattrs-include='*', which we don't pass. Now, passing this option when creating and extracting the intermediate tarball, both done under fakeroot, will cause fakeroot to report an invalid filetype for files with capabilities. mksquashfs would report such unknown files as a warning, while mkfs.ext2 would fail (with a similar error message), e.g.: File [...]/usr/sbin/getcap has unrecognised filetype 0, ignoring This is due to a poor interaction between tar and fakeroot; running as root the exact same commands we run under fakeroot, works as expected. Unfortunately, short of fixing fakeroot (which would first require understanding the problem in there), we don't have much options. The intermediate tarball was made to avoid redoing the same actions over and over again for each filesystem to build. However, most of the time, only one or two such filesystems would be enabled [0], and those actions are usually pretty lightweight. So, using an intermediate tarball does not provide a big optimisation. The main reason to introduce the intermediate tarball, however, is that it allows to postpone per-filesystem finalisations to be applied only for the corresponding filesystem, not for all of them. So, we get rid of the intermediate tarball, and simply move all of the code to run under fakeroot to the per-filesystem fakeroot script. Instead of extracting the intermediate tarball, we just rsync the original target/ directory, and apply the filesystem finalisations on that copy. The only thing still done in the rootfs-common step is to generate the intermediate files (users file, devices file) that are used in the fakeroot script. Fixes: https://bugs.busybox.net/show_bug.cgi?id=11216 Note: an alternate solution would have been to keep the intermediate tarball to keep most of the common finalisations, and move only the permissions to each filesystem, but that was getting a bit more complex and changed the ordering of permissions and post-fakeroot scripts. Once we bite the bullet of having some common finalisation done in each filesystem, it's easier to just move all of them. [0] Most probsably, users would enable the real filesystem to put on their device, plus the 'tar' filesystem, to be able to easily inspect the content on their development machine. Reported-by: Ricardo Martincoski <ricardo.martincoski@gmail.com> Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Ricardo Martincoski <ricardo.martincoski@gmail.com> Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Cc: Arnout Vandecappelle <arnout@mind.be> Cc: Peter Korsgaard <peter@korsgaard.com> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
2018-11-13 01:33:11 +08:00
echo "chown -h -R 0:0 $$(TARGET_DIR)" >> $$(FAKEROOT_SCRIPT)
PATH=$$(BR_PATH) $$(TOPDIR)/support/scripts/mkusers $$(USERS_TABLE) $$(TARGET_DIR) >> $$(FAKEROOT_SCRIPT)
echo "$$(HOST_DIR)/bin/makedevs -d $$(FULL_DEVICE_TABLE) $$(TARGET_DIR)" >> $$(FAKEROOT_SCRIPT)
$$(foreach s,$$(call qstrip,$$(BR2_ROOTFS_POST_FAKEROOT_SCRIPT)),\
echo "echo '$$(TERM_BOLD)>>> Executing fakeroot script $$(s)$$(TERM_RESET)'" >> $$(FAKEROOT_SCRIPT); \
echo $$(EXTRA_ENV) $$(s) $$(TARGET_DIR) $$(BR2_ROOTFS_POST_SCRIPT_ARGS) >> $$(FAKEROOT_SCRIPT)$$(sep))
$$(foreach hook,$$(ROOTFS_PRE_CMD_HOOKS),\
$$(call PRINTF,$$($$(hook))) >> $$(FAKEROOT_SCRIPT)$$(sep))
$$(foreach hook,$$(ROOTFS_$(2)_PRE_GEN_HOOKS),\
$$(call PRINTF,$$($$(hook))) >> $$(FAKEROOT_SCRIPT)$$(sep))
$$(call PRINTF,$$(ROOTFS_REPRODUCIBLE)) >> $$(FAKEROOT_SCRIPT)
$$(call PRINTF,$$(ROOTFS_$(2)_CMD)) >> $$(FAKEROOT_SCRIPT)
chmod a+x $$(FAKEROOT_SCRIPT)
PATH=$$(BR_PATH) $$(HOST_DIR)/bin/fakeroot -- $$(FAKEROOT_SCRIPT)
$(Q)rm -rf $$(TARGET_DIR)
ifneq ($$(ROOTFS_$(2)_COMPRESS_CMD),)
infra: consistently use double dollar signs inside inner-xxx-targets The inner-xxx-targets in the buildroot package infrastructures are evaluated using $(eval) which causes variable references to be a bit different than in regular make code. As we want most references to be expanded only at the time of the $(eval) we should not use standard references $(VAR) but rather use double dollar signs $$(VAR). This includes function references like $(call), $(subst), etc. The only exception is the reference to pkgdir/pkgname and numbered variables, which are parameters to the inner block: $(1), $(2), etc. This patch introduces consistent usage of double-dollar signs throughout the different inner-xxx-targets blocks. In some cases, this would potentially cause circular references, in particular when the value of HOST_FOO_VAR would be obtained from the corresponding FOO_VAR if HOST_FOO_VAR is not defined. In these cases, a test is added to check for a host package (the only case where such constructions are relevant; these are not circular). Benefits of these changes are: - behavior of variables is now again as expected. For example, setting $(2)_VERSION = virtual in pkg-virtual.mk will effectively work, while originally it would cause very odd results. - The output of 'make printvars' is now much more useful. This target shows the value of all variables, and the expression that led to that value. However, if the expression was coming from an inner-xxx-targets block, and was using single dollar signs, it would show in printvars as VAR = value (value) while if double dollar signs are used, it would effectively look like VAR = value (actual expression) as is intended. This improvement is for example effective for FOO_DL_VERSION, FOO_RAWNAME, FOO_SITE_METHOD and FOO_MAKE. The correctness of this patch has been verified using 'make printvars', 'make manual' and 'make legal-info' before and after applying this patch, and comparing the output. Insight-provided-by: Arnout Vandecappelle <arnout@mind.be> Signed-off-by: Thomas De Schampheleire <thomas.de.schampheleire@gmail.com> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2014-06-12 03:12:24 +08:00
PATH=$$(BR_PATH) $$(ROOTFS_$(2)_COMPRESS_CMD) $$@ > $$@$$(ROOTFS_$(2)_COMPRESS_EXT)
endif
$$(foreach hook,$$(ROOTFS_$(2)_POST_GEN_HOOKS),$$(call $$(hook))$$(sep))
rootfs-$(1)-show-depends:
@echo $$(ROOTFS_$(2)_DEPENDENCIES)
rootfs-$(1): $$(BINARIES_DIR)/$$(ROOTFS_$(2)_FINAL_IMAGE_NAME)
.PHONY: rootfs-$(1) rootfs-$(1)-show-depends
ifeq ($$(BR2_TARGET_ROOTFS_$(2)),y)
TARGETS_ROOTFS += rootfs-$(1)
PACKAGES += $$(filter-out rootfs-%,$$(ROOTFS_$(2)_DEPENDENCIES) $$(ROOTFS_COMMON_DEPENDENCIES))
endif
# Check for legacy POST_TARGETS rules
ifneq ($$(ROOTFS_$(2)_POST_TARGETS),)
$$(error Filesystem $(1) uses post-target rules, which are no longer supported.\
Update $(1) to use post-gen hooks instead)
endif
endef
# $(pkgname) also works well to return the filesystem name
rootfs = $(call inner-rootfs,$(pkgname),$(call UPPERCASE,$(pkgname)))
include $(sort $(wildcard fs/*/*.mk))