All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnout Vandecappelle <arnout@mind.be>
To: buildroot@busybox.net
Subject: [Buildroot] [PATCH next v6 07/10] core: implement per-package SDK and target
Date: Tue, 4 Dec 2018 23:24:58 +0100	[thread overview]
Message-ID: <dc8cc6eb-59ab-2913-f094-cf5ae48eec4d@mind.be> (raw)
In-Reply-To: <20181123145815.13008-8-thomas.petazzoni@bootlin.com>

 Hi Thomas,

 A few random remarks.

On 23/11/2018 15:58, Thomas Petazzoni wrote:
> This commit implements the core of the move to per-package SDK and
> target directories. The main idea is that instead of having a global
> output/host and output/target in which all packages install files, we
> switch to per-package host and target directories, that only contain
> their explicit dependencies.
> 
> There are two main benefits:
> 
>  - Packages will no longer discover dependencies that they do not
>    explicitly indicate in their <pkg>_DEPENDENCIES variable.
> 
>  - We can support top-level parallel build properly, because a package
>    only "sees" its own host directory and target directory, isolated
>    from the build of other packages that can happen in parallel.
> 
> It works as follows:
> 
>  - A new output/per-package/ directory is created, which will contain
>    one sub-directory per package, and inside it, a "host" directory
>    and a "target" directory:
> 
>    output/per-package/busybox/target
>    output/per-package/busybox/host
>    output/per-package/host-fakeroot/target
>    output/per-package/host-fakeroot/host
> 
>    This output/per-package/ directory is PER_PACKAGE_DIR.
> 
>  - The global TARGET_DIR and HOST_DIR variable now automatically point
>    to the per-package directory when PKG is defined. So whenever a
>    package references $(HOST_DIR) or $(TARGET_DIR) in its build
>    process, it effectively references the per-package host/target
>    directories. Note that STAGING_DIR is a sub-dir of HOST_DIR, so it
>    is handled as well.
> 
>  - Of course, packages have dependencies, so those dependencies must
>    be installed in the per-package host and target directories. To do
>    so, we simply rsync (using hard links to save space and time) the
>    host and target directories of the direct dependencies of the
>    package to the current package host and target directories.
> 
>    We only need to take care of direct dependencies (and not
>    recursively all dependencies), because we accumulate into those
>    per-package host and target directories the files installed by the
>    dependencies. Note that this only works because we make the
>    assumption that one package does *not* overwrite files installed by
>    another package.

 So that means that if BR2_PER_PACKAGE_DIRECTORIES=y, check-uniq-files should
give errors instead of warnings, no?

> 
>    This is done for "extract dependencies" at the beginning of the
>    extract step, and for "normal dependencies" at the beginning of the
>    configure step.
> 
> This is basically enough to make per-package SDK and target work. The
> only gotcha is that at the end of the build, output/target and
> output/host are empty, which means that:
> 
>  - The filesystem image creation code cannot work.
> 
>  - We don't have a SDK to build code outside of Buildroot.
> 
> In order to fix this, this commit extends the target-finalize step so
> that it starts by populating output/target and output/host by
> rsync-ing into them the target and host directories of all packages
> listed in the $(PACKAGES) variable. It is necessary to do this
> sequentially in the target-finalize step and not in each
> package. Doing it in package installation means that it can be done in
> parallel. In that case, there is a chance that two rsyncs are creating
> the same hardlink or directory at the same time, which makes one of
> them fail.

 Great that this is explained in the commit log.

> 
> Also, with this change to per-package directories, binaries built for
> the host may contain RPATH pointing to per-package directories. This
> commit therefore teaches the check-host-rpath script with the fact
> that RPATH pointing to a per-package directory are OK.
> 
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
> ---
>  Config.in                        | 18 ++++++++++++++++
>  Makefile                         | 36 +++++++++++++++++++++++++++-----
>  package/pkg-generic.mk           |  5 ++++-
>  package/pkg-utils.mk             | 21 +++++++++++++++++++
>  support/scripts/check-host-rpath |  5 ++++-
>  5 files changed, 78 insertions(+), 7 deletions(-)
> 
> diff --git a/Config.in b/Config.in
> index f965e9d6d8..2d8a07fda7 100644
> --- a/Config.in
> +++ b/Config.in
> @@ -696,6 +696,24 @@ config BR2_REPRODUCIBLE
>  	  This is labeled as an experimental feature, as not all
>  	  packages behave properly to ensure reproducibility.
>  
> +config BR2_PER_PACKAGE_DIRECTORIES
> +	bool "Use per-package directories (experimental)"
> +	help
> +	  This option will change the build process of Buildroot
> +	  package to use per-package target and host directories.
> +
> +	  This is useful for two related purposes:
> +
> +	    - Cleanly isolate the build of each package, so that a
> +	      given package only "sees" the dependencies it has
> +	      explicitly expressed, and not other packages that may
> +	      have by chance been built before.
> +
> +	    - Enable top-level parallel build.
> +
> +	  This is labeled as an experimental feature, as not all
> +	  packages behave properly with per-package directories.
> +
>  endmenu
>  
>  comment "Security Hardening Options"
> diff --git a/Makefile b/Makefile
> index 23032988a5..35fe1b3644 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -207,7 +207,8 @@ BINARIES_DIR := $(BASE_DIR)/images
>  # The target directory is common to all packages,
>  # but there is one that is specific to each filesystem.
>  BASE_TARGET_DIR := $(BASE_DIR)/target
> -TARGET_DIR = $(if $(ROOTFS),$(ROOTFS_$(ROOTFS)_TARGET_DIR),$(BASE_TARGET_DIR))
> +PER_PACKAGE_DIR := $(BASE_DIR)/per-package

 Perhaps it would be nice to add a preparatory patch that reorders the
definitions of BASE_TARGET_DIR, TARGET_DIR, STAGING_DIR and HOST_DIR so they are
all together, and can be in a single BR2_PER_PACKAGE_DIRECTORIES condition.

> +
>  # initial definition so that 'make clean' works for most users, even without
>  # .config. HOST_DIR will be overwritten later when .config is included.
>  HOST_DIR := $(BASE_DIR)/host
> @@ -246,6 +247,12 @@ endif
>  #      make -j$((`getconf _NPROCESSORS_ONLN`+1))
>  .NOTPARALLEL:
>  
> +ifeq ($(BR2_PER_PACKAGE_DIRECTORIES),y)
> +TARGET_DIR = $(if $(ROOTFS),$(ROOTFS_$(ROOTFS)_TARGET_DIR),$(if $(PKG),$(PER_PACKAGE_DIR)/$($(PKG)_NAME)/target,$(BASE_TARGET_DIR)))
> +else
> +TARGET_DIR = $(if $(ROOTFS),$(ROOTFS_$(ROOTFS)_TARGET_DIR),$(BASE_TARGET_DIR))
> +endif

 Was there any reason to move the definition of TARGET_DIR?

> +
>  # timezone and locale may affect build output
>  ifeq ($(BR2_REPRODUCIBLE),y)
>  export TZ = UTC
> @@ -455,7 +462,11 @@ LZCAT := $(call qstrip,$(BR2_LZCAT))
>  TAR_OPTIONS = $(call qstrip,$(BR2_TAR_OPTIONS)) -xf
>  
>  # packages compiled for the host go here
> +ifeq ($(BR2_PER_PACKAGE_DIRECTORIES),y)
> +HOST_DIR = $(if $(PKG),$(PER_PACKAGE_DIR)/$($(PKG)_NAME)/host,$(call qstrip,$(BR2_HOST_DIR)))
> +else
>  HOST_DIR := $(call qstrip,$(BR2_HOST_DIR))
> +endif
>  
>  ifneq ($(HOST_DIR),$(BASE_DIR)/host)
>  HOST_DIR_SYMLINK = $(BASE_DIR)/host
> @@ -701,14 +712,28 @@ $(TARGETS_ROOTFS): target-finalize
>  # Avoid the rootfs name leaking down the dependency chain
>  target-finalize: ROOTFS=
>  
> -host-finalize: $(HOST_DIR_SYMLINK)
> +host-finalize: $(PACKAGES) $(HOST_DIR) $(HOST_DIR_SYMLINK)
> +ifeq ($(BR2_PER_PACKAGE_DIRECTORIES),y)	
> +	@$(call MESSAGE,"Creating global host directory")
> +	$(foreach pkg,$(sort $(PACKAGES)),\
> +		rsync -a --link-dest=$(PER_PACKAGE_DIR)/$(pkg)/host/ \
> +		$(PER_PACKAGE_DIR)/$(pkg)/host/ \
> +		$(HOST_DIR)$(sep))

 Don't you think it's worth factoring this into a pkg-utils macro? I'm thinking:

# rsync-per-package(packages,type,destdir)
# copy every per-package host or target dir (as determined by type) for packages
# (a list of packages) into destdir.
# copying is done by making hardlinks using rsync
define rsync-per-package
	$(foreach pkg,$(sort $(1)),\
		rsync -a --link-dest=$(PER_PACKAGE_DIR)/$(pkg)/$(2)/ \
		$(PER_PACKAGE_DIR)/$(pkg)/$(2)/ \
		$(3)$(sep))
endef

rsync-per-package-host = $(call rsync-per-package,$(1),host,$(HOST_DIR))
rsync-per-package-target = $(call rsync-per-package,$(1),target,$(TARGET_DIR))

The latter two are maybe not needed.

> +endif
>  
>  .PHONY: staging-finalize
>  staging-finalize:
>  	@ln -snf $(STAGING_DIR) $(BASE_DIR)/staging
>  
>  .PHONY: target-finalize
> -target-finalize: $(PACKAGES) host-finalize
> +target-finalize: $(PACKAGES) $(TARGET_DIR) host-finalize
> +ifeq ($(BR2_PER_PACKAGE_DIRECTORIES),y)
> +	@$(call MESSAGE,"Creating global target directory")
> +	$(foreach pkg,$(sort $(PACKAGES)),\
> +		rsync -a --link-dest=$(PER_PACKAGE_DIR)/$(pkg)/target/ \
> +		$(PER_PACKAGE_DIR)/$(pkg)/target/ \
> +		$(TARGET_DIR)$(sep))
> +endif
>  	@$(call MESSAGE,"Finalizing target directory")
>  	# Check files that are touched by more than one package
>  	./support/scripts/check-uniq-files -t target $(BUILD_DIR)/packages-file-list.txt

 Side note: if we make check-uniq-files return errors, we should probably also
move it to a per package step so the autobuilders can identify the failing
package. But that can be done later.

[snip]
> diff --git a/support/scripts/check-host-rpath b/support/scripts/check-host-rpath
> index 6c5767da05..787a1763b0 100755
> --- a/support/scripts/check-host-rpath
> +++ b/support/scripts/check-host-rpath
> @@ -11,6 +11,7 @@ export LC_ALL=C
>  main() {
>      local pkg="${1}"
>      local hostdir="${2}"
> +    local perpackagedir="${3}"
>      local file ret
>  
>      # Remove duplicate and trailing '/' for proper match
> @@ -20,7 +21,7 @@ main() {
>      while read file; do
>          is_elf "${file}" || continue
>          elf_needs_rpath "${file}" "${hostdir}" || continue
> -        check_elf_has_rpath "${file}" "${hostdir}" && continue
> +        check_elf_has_rpath "${file}" "${hostdir}" "${perpackagedir}" && continue
>          if [ ${ret} -eq 0 ]; then
>              ret=1
>              printf "***\n"
> @@ -57,6 +58,7 @@ elf_needs_rpath() {

 I think there should be some explanation why elf_needs_rpath doesn't need to
check all per-package directories. Basically it's because any library that the
executable may depend on must already have been rsynced into ${host_dir} which
is the per-package host directory.

 Regards,
 Arnout


>  check_elf_has_rpath() {
>      local file="${1}"
>      local hostdir="${2}"
> +    local perpackagedir="${3}"
>      local rpath dir
>  
>      while read rpath; do
> @@ -65,6 +67,7 @@ check_elf_has_rpath() {
>              dir="$( sed -r -e 's:/+:/:g; s:/$::;' <<<"${dir}" )"
>              [ "${dir}" = "${hostdir}/lib" ] && return 0
>              [ "${dir}" = "\$ORIGIN/../lib" ] && return 0
> +            [[ ${dir} =~ ${perpackagedir}/[^/]*/host/lib ]] && return 0
>          done
>      done < <( readelf -d "${file}"                                              \
>                |sed -r -e '/.* \(R(UN)?PATH\) +Library r(un)?path: \[(.+)\]$/!d' \
> 

  parent reply	other threads:[~2018-12-04 22:24 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-23 14:58 [Buildroot] [PATCH next v6 00/10] Per-package host/target directory support Thomas Petazzoni
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 01/10] Makefile: evaluate CCACHE and HOST{CC, CXX} at time of use Thomas Petazzoni
2018-11-26 18:14   ` Peter Korsgaard
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 02/10] support/scripts/check-host-rpath: split condition on two statements Thomas Petazzoni
2018-11-26 18:14   ` Peter Korsgaard
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 03/10] Makefile: rework main directory creation logic Thomas Petazzoni
2018-11-23 18:07   ` Yann E. MORIN
2018-11-26 18:14   ` Peter Korsgaard
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 04/10] Makefile: move .NOTPARALLEL statement after including .config file Thomas Petazzoni
2018-11-26 18:15   ` Peter Korsgaard
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 05/10] Makefile: define TARGET_DIR_WARNING_FILE relative to TARGET_DIR Thomas Petazzoni
2018-11-26 18:15   ` Peter Korsgaard
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 06/10] package/pkg-generic: adjust config scripts tweaks for per-package directories Thomas Petazzoni
2018-11-23 18:09   ` Yann E. MORIN
2018-11-26 18:15   ` Peter Korsgaard
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 07/10] core: implement per-package SDK and target Thomas Petazzoni
2018-11-23 21:50   ` Yann E. MORIN
2018-12-04 22:24   ` Arnout Vandecappelle [this message]
2018-12-05  8:04     ` Thomas Petazzoni
2018-12-05  9:18       ` Arnout Vandecappelle
2018-12-05  9:44         ` Thomas Petazzoni
2018-12-05 10:41           ` Arnout Vandecappelle
2018-12-05 16:08   ` Andreas Naumann
2018-12-05 16:31     ` Thomas Petazzoni
2018-12-05 16:52       ` Andreas Naumann
2018-12-06 10:21         ` Andreas Naumann
2018-12-06 10:28           ` Thomas Petazzoni
2018-12-06 10:42             ` Andreas Naumann
2018-12-06 10:58               ` Thomas Petazzoni
2018-12-06 13:31                 ` Andreas Naumann
2018-12-26 17:34           ` Thomas Petazzoni
2018-12-26 18:33             ` Thomas De Schampheleire
2019-01-10 21:25               ` Arnout Vandecappelle
2019-01-11 20:09                 ` Thomas De Schampheleire
2019-01-13 22:10                   ` Arnout Vandecappelle
2019-01-14 16:01                     ` Thomas De Schampheleire
2019-01-14 16:33                       ` Thomas Petazzoni
2019-01-14 20:19                       ` Thomas De Schampheleire
2019-01-14 20:43                         ` Thomas De Schampheleire
2018-12-26 18:58             ` Yann E. MORIN
2018-12-27 16:17             ` Thomas Petazzoni
2019-01-10 21:14               ` Arnout Vandecappelle
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 08/10] Makefile: allow top-level parallel build with BR2_PER_PACKAGE_DIRECTORIES=y Thomas Petazzoni
2018-11-23 18:11   ` Yann E. MORIN
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 09/10] package/pkg-generic: make libtool .la files compatible with per-package directories Thomas Petazzoni
2018-11-25 17:57   ` Yann E. MORIN
2018-11-30 10:20     ` Thomas Petazzoni
2018-12-01 10:59       ` Yann E. MORIN
2018-11-23 14:58 ` [Buildroot] [PATCH next v6 10/10] package/pkg-kconfig: handle KCONFIG_DEPENDENCIES " Thomas Petazzoni
2018-11-25 17:57   ` Yann E. MORIN
2018-12-05 15:23   ` Andreas Naumann
2018-12-06 14:07     ` Andreas Naumann
2018-12-06 14:25       ` Thomas Petazzoni
2018-12-26 16:40       ` Thomas Petazzoni

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dc8cc6eb-59ab-2913-f094-cf5ae48eec4d@mind.be \
    --to=arnout@mind.be \
    --cc=buildroot@busybox.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.