diff --git a/bootstrap-conda b/bootstrap-conda index c64e2a72b6c..e1a7476b90e 100755 --- a/bootstrap-conda +++ b/bootstrap-conda @@ -10,7 +10,8 @@ STRIP_COMMENTS="sed s/#.*//;" shopt -s extglob -DEVELOP_SPKG_PATTERN="@(_develop$(for a in $(head -n 1 build/pkgs/_develop/dependencies); do echo -n "|"$a; done))" +eval $(sage-package dependencies --format=shell :all:) +DEVELOP_SPKG_PATTERN="@(_develop|${runtime_deps__develop// /|})" BOOTSTRAP_PACKAGES=_bootstrap PACKAGES= OPTIONAL_PACKAGES= @@ -139,18 +140,22 @@ echo >&2 $0:$LINENO: generate conda environment files if [ ! -f $SYSTEM_PACKAGES_FILE ]; then SYSTEM_PACKAGES_FILE=$PKG_SCRIPTS/version_requirements.txt fi - if grep -q SAGERUNTIME $PKG_SCRIPTS/dependencies $PKG_SCRIPTS/dependencies_order_only 2>/dev/null; then - : # cannot install packages that depend on the Sage library - else - case "$PKG_BASE:$PKG_TYPE" in - $DEVELOP_SPKG_PATTERN:*) FD=4;; - *:standard) FD="4 5";; - *) FD=5;; - esac - ${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE | while read -r line; do - [ -n "$line" ] && for fd in $FD; do echo >&$fd " - $line"; done - done - fi + eval DEPS=\"\$runtime_deps_$PKG_BASE\ \$build_deps_$PKG_BASE\ \$order_only_deps_$PKG_BASE\" + case "$DEPS" in + *SAGERUNTIME*) + # cannot install packages that depend on the Sage library + ;; + *) + case "$PKG_BASE:$PKG_TYPE" in + $DEVELOP_SPKG_PATTERN:*) FD=4;; + *:standard) FD="4 5";; + *) FD=5;; + esac + ${STRIP_COMMENTS} $SYSTEM_PACKAGES_FILE | while read -r line; do + [ -n "$line" ] && for fd in $FD; do echo >&$fd " - $line"; done + done + ;; + esac done ) 4>> /dev/null 5>> src/environment-optional-template.yml diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 420dadb9364..75c0c9acd57 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -187,7 +187,6 @@ $(foreach pkgname,$(PIP_PACKAGES),\ $(SAGE_LOCAL)/$(SPKG_INST_RELDIR)/.dummy: touch $@ - # Filtered by installation tree $(foreach tree,SAGE_LOCAL SAGE_VENV SAGE_DOCS, \ $(eval $(tree)_INSTALLED_PACKAGE_INSTS = \ @@ -199,6 +198,9 @@ $(foreach tree,SAGE_LOCAL SAGE_VENV SAGE_DOCS, \ $(if $(findstring $(tree),$(trees_$(pkgname))), \ $(inst_$(pkgname)))))) +# Optional dependencies +$(foreach pkgname,$(INSTALLED_PACKAGES),\ + $(eval optional_inst_$(pkgname) = $(inst_$(pkgname)))) ############################################################################### @@ -548,10 +550,11 @@ debug-check: # # Positional arguments: # $(1): package name +# $(2): empty or one of "build_", "check_" pkg_deps = \ $(if $(filter gcc,$(1)),,$$(GCC_DEP))\ - $(foreach dep,$(deps_$(1)),\ - $(if $(value inst_$(dep)),$$(inst_$(dep)),$(dep))) + $(foreach dep,$($(2)deps_$(1)),\ + $(if $(value inst_$(dep)),$$(inst_$(dep)),$(dep))) # ============================= normal packages ============================== # Generate build rules for 'normal' packages; this template is used to generate @@ -599,62 +602,73 @@ pkg_deps = \ # Positional arguments: # $(1): package name # $(2): package version -# $(3): package dependencies -# $(4): package tree variable +# $(3): package build dependencies +# $(4): package dependencies +# $(5): package check dependencies +# $(6): package tree variable define NORMAL_PACKAGE_templ ########################################## $(1)-build-deps: $(3) -$$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2): $(3) - +$(MAKE_REC) $(1)-$(4)-no-deps +$(1)-deps: $(1)-build-deps $(4) -$(1): $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2) +$$($(6))/$(SPKG_INST_RELDIR)/$(1)-$(2): $(4) $(3) $(if $(check_deps_$(1)),$$(and $$(filter-out no,$$(SAGE_CHECK_$(1))),$(5))) + +$(MAKE_REC) $(1)-$(6)-no-deps -$(1)-ensure: $(inst_$(1)) +$(1): $$($(6))/$(SPKG_INST_RELDIR)/$(1)-$(2) -$(1)-$(4)-no-deps: - +@if [ -z '$$($(4))' ]; then \ - echo "Error: The installation tree $(4) has been disabled" 2>&1; \ - echo "$$($(4)_DISABLED_MESSAGE)" 2>&1; \ +$(1)-ensure: $$(inst_$(1)) + +$(1)-$(6)-build-no-deps: + +@if [ -z '$$($(6))' ]; then \ + echo "Error: The installation tree $(6) has been disabled" 2>&1; \ + echo "$$($(6)_DISABLED_MESSAGE)" 2>&1; \ exit 1; \ - else \ - sage-logger -p 'SAGE_CHECK=$$(SAGE_CHECK_$(1)) PATH=$$(SAGE_SRC)/bin:$$($(4))/bin:$$$$PATH $$(SAGE_SPKG) $$(SAGE_SPKG_OPTIONS) \ - $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-existing) \ - $(1)-$(2) $$($(4))' '$$(SAGE_LOGS)/$(1)-$(2).log'; \ fi -$(1)-no-deps: $(1)-$(4)-no-deps +$(1)-build-no-deps: $(1)-$(6)-build-no-deps -$(1)-$(4)-check: - $(PLUS)@sage-logger -p 'PATH=$$(SAGE_SRC)/bin:$$($(4))/bin:$$$$PATH $$(SAGE_SPKG) --check-only $(1)-$(2) $$($(4))' '$$(SAGE_LOGS)/$(1)-$(2).log' +$(1)-$(6)-no-deps: $(1)-$(6)-build-no-deps + +@sage-logger -p 'SAGE_CHECK=$$(SAGE_CHECK_$(1)) PATH=$$(SAGE_SRC)/bin:$$($(6))/bin:$$$$PATH $$(SAGE_SPKG) $$(SAGE_SPKG_OPTIONS) \ + $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-existing) \ + $(1)-$(2) $$($(6))' '$$(SAGE_LOGS)/$(1)-$(2).log'; \ -$(1)-check: $(1)-$(4)-check +$(1)-no-deps: $(1)-$(6)-no-deps -$(1)-$(4)-uninstall: - if [ -d '$$($(4))' ]; then \ +$(1)-$(6)-check: + $(PLUS)@sage-logger -p 'PATH=$$(SAGE_SRC)/bin:$$($(6))/bin:$$$$PATH $$(SAGE_SPKG) --check-only $(1)-$(2) $$($(6))' '$$(SAGE_LOGS)/$(1)-$(2).log' + +$(1)-check: $(1)-$(6)-check + +$(1)-$(6)-uninstall: + if [ -d '$$($(6))' ]; then \ sage-spkg-uninstall $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-files) \ - $(1) '$$($(4))'; \ + $(1) '$$($(6))'; \ fi -$(1)-uninstall: $(1)-$(4)-uninstall +$(1)-uninstall: $(1)-$(6)-uninstall $(1)-clean: $(1)-uninstall -.PHONY: $(1) $(1)-$(4)-uninstall $(1)-uninstall $(1)-clean $(1)-build-deps $(1)-no-deps +.PHONY: $(1) $(1)-$(6)-uninstall $(1)-uninstall $(1)-clean $(1)-build-deps $(1)-no-deps endef ################################################################# $(foreach pkgname, $(NORMAL_PACKAGES),\ $(foreach tree, $(trees_$(pkgname)), \ $(eval $(call NORMAL_PACKAGE_templ,$(pkgname),$(vers_$(pkgname)),\ - $(call pkg_deps,$(pkgname)),$(tree))))) + $(call pkg_deps,$(pkgname),build_),\ + $(call pkg_deps,$(pkgname)),\ + $(call pkg_deps,$(pkgname),check_),$(tree))))) ifdef DEBUG_RULES $(info # Rules for standard packages) $(foreach pkgname, $(NORMAL_PACKAGES),\ $(foreach tree, $(trees_$(pkgname)), \ $(info $(call NORMAL_PACKAGE_templ,$(pkgname),$(vers_$(pkgname)),\ - $(call pkg_deps,$(pkgname)),$(tree))))) + $(call pkg_deps,$(pkgname),build_),\ + $(call pkg_deps,$(pkgname)),\ + $(call pkg_deps,$(pkgname),check_),$(tree))))) endif # ================================ pip packages =============================== @@ -669,14 +683,17 @@ endif # Positional arguments: # $(1): package name -# $(2): package dependencies +# $(2): package build dependencies +# $(3): package dependencies define PIP_PACKAGE_templ $(1)-build-deps: $(2) -$(1): $(2) +$(1)-deps: $(1)-build-deps $(3) + +$(1): $(3) $(2) +$(MAKE_REC) $(1)-no-deps -$(1)-ensure: $(inst_$(1)) +$(1)-ensure: $$(inst_$(1)) $(1)-no-deps: $(AM_V_at)sage-logger -p 'sage --pip install -r "$$(SAGE_ROOT)/build/pkgs/$(1)/requirements.txt"' '$$(SAGE_LOGS)/$(1).log' @@ -690,12 +707,14 @@ $(1)-clean: $(1)-uninstall endef $(foreach pkgname,$(PIP_PACKAGES),\ - $(eval $(call PIP_PACKAGE_templ,$(pkgname),$(call pkg_deps,$(pkgname))))) + $(eval $(call PIP_PACKAGE_templ,$(pkgname),$(call pkg_deps,$(pkgname),build_),\ + $(call pkg_deps,$(pkgname))))) ifdef DEBUG_RULES $(info # Rules for pip packages) $(foreach pkgname,$(PIP_PACKAGES),\ - $(info $(call PIP_PACKAGE_templ,$(pkgname),$(call pkg_deps,$(pkgname))))) + $(info $(call PIP_PACKAGE_templ,$(pkgname),$(call pkg_deps,$(pkgname),build_),\ + $(call pkg_deps,$(pkgname))))) endif # ============================= script packages ============================== @@ -795,13 +814,13 @@ endef $(foreach pkgname,$(SCRIPT_PACKAGES),\ $(foreach tree, $(trees_$(pkgname)), \ - $(eval $(call SCRIPT_PACKAGE_templ,$(pkgname),$(vers_$(pkgname)),$(call pkg_deps,$(pkgname)),$(tree))))) + $(eval $(call SCRIPT_PACKAGE_templ,$(pkgname),$(vers_$(pkgname)),$(call pkg_deps,$(pkgname),build_),$(tree))))) ifdef DEBUG_RULES $(info # Rules for script packages) $(foreach pkgname,$(SCRIPT_PACKAGES),\ $(foreach tree, $(trees_$(pkgname)), \ - $(info $(call SCRIPT_PACKAGE_templ,$(pkgname),$(vers_$(pkgname)),$(call pkg_deps,$(pkgname)),$(tree))))) + $(info $(call SCRIPT_PACKAGE_templ,$(pkgname),$(vers_$(pkgname)),$(call pkg_deps,$(pkgname),build_),$(tree))))) endif # sagelib depends on this so that its install script is always executed diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 2b8b44959b1..f4d070456d9 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -131,12 +131,12 @@ def dependencies(self, *package_classes, **kwds): pc = PackageClass(*package_classes) if format in ['plain', 'rst']: if types is None: - typesets = [['order_only', 'runtime']] + typesets = [['build', 'order_only', 'runtime']] else: typesets = [[t] for t in types] elif format == 'shell': if types is None: - types = ['order_only', 'optional', 'runtime', 'check'] + types = ['build', 'order_only', 'optional', 'runtime', 'check'] typesets = [[t] for t in types] else: raise ValueError('format must be one of "plain", "rst", and "shell"') diff --git a/build/sage_bootstrap/cmdline.py b/build/sage_bootstrap/cmdline.py index cbd4a544bb6..f1a979cd8ed 100644 --- a/build/sage_bootstrap/cmdline.py +++ b/build/sage_bootstrap/cmdline.py @@ -325,6 +325,9 @@ def make_parser(): type=str, nargs='+', help=('package name or designator for all packages of a given type ' '(one of :all:, :standard:, :optional:, and :experimental:)')) + parser_dependencies.add_argument( + '--build', action='store_true', + help='list the (ordinary) build dependencies') parser_dependencies.add_argument( '--order-only', action='store_true', help='list the order-only build dependencies') @@ -507,6 +510,8 @@ def run(): app.properties(*args.package_class, format=args.format) elif args.subcommand == 'dependencies': types = [] + if args.build: + types.append('build') if args.order_only: types.append('order_only') if args.optional: diff --git a/build/sage_bootstrap/creator.py b/build/sage_bootstrap/creator.py index e16002f12f9..0eeb7e4788a 100644 --- a/build/sage_bootstrap/creator.py +++ b/build/sage_bootstrap/creator.py @@ -108,7 +108,7 @@ def _remove_files(self, files): def set_python_data_and_scripts(self, pypi_package_name=None, source='normal', dependencies=None): """ - Write the file ``dependencies`` and other files for Python packages. + Write the files ``dependencies``, ``dependencies_build``, and other files for Python packages. If ``source`` is ``"normal"``, write the files ``spkg-install.in`` and ``version_requirements.txt``. @@ -121,16 +121,14 @@ def set_python_data_and_scripts(self, pypi_package_name=None, source='normal', d """ if pypi_package_name is None: pypi_package_name = self.package_name - with open(os.path.join(self.path, 'dependencies'), 'w+') as f: - if dependencies: - dependencies = ' '.join(dependencies) - else: - dependencies = '' + with open(os.path.join(self.path, 'dependencies_build'), 'w+') as f: if source == 'wheel': - dependencies_order_only = 'pip $(PYTHON)' + f.write(' | pip $(PYTHON)\n\n') else: - dependencies_order_only = '$(PYTHON_TOOLCHAIN) $(PYTHON)' - f.write(dependencies + ' | ' + dependencies_order_only + '\n\n') + f.write(' | $(PYTHON_TOOLCHAIN) $(PYTHON)\n\n') + f.write('----------\nAll lines of this file are ignored except the first.\n') + with open(os.path.join(self.path, 'dependencies'), 'w+') as f: + f.write('# No dependencies\n\n') f.write('----------\nAll lines of this file are ignored except the first.\n') if source == 'normal': with open(os.path.join(self.path, 'spkg-install.in'), 'w+') as f: diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index c063af0c816..d52cf77c36b 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -414,19 +414,26 @@ def distribution_name(self): return None @property - def dependencies(self): + def dependencies_build(self): """ - Return a list of strings, the package names of the (ordinary) dependencies + Return a list of strings, the package names of the (ordinary) build dependencies """ - # after a '|', we have order-only dependencies - return self.__dependencies.partition('|')[0].strip().split() + if self.__dependencies_build is None: + deps = self.__dependencies + else: + deps = self.__dependencies_build + return deps.partition('|')[0].strip().split() @property def dependencies_order_only(self): """ - Return a list of strings, the package names of the order-only dependencies + Return a list of strings, the package names of the order-only build dependencies """ - return self.__dependencies.partition('|')[2].strip().split() + self.__dependencies_order_only.strip().split() + if self.__dependencies_build is None: + deps = self.__dependencies + else: + deps = self.__dependencies_build + return deps.partition('|')[2].strip().split() + self.__dependencies_order_only.strip().split() @property def dependencies_optional(self): @@ -592,6 +599,11 @@ def _init_dependencies(self): self.__dependencies_order_only = f.readline().partition('#')[0].strip() except IOError: self.__dependencies_order_only = '' + try: + with open(os.path.join(self.path, 'dependencies_build')) as f: + self.__dependencies_build = f.readline().partition('#')[0].strip() + except IOError: + self.__dependencies_build = None def _init_trees(self): try: diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index 231193ce8fb..e36da1c0db5 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -79,8 +79,8 @@ AS_BOX([Build status for each package: ] AS_BOX([Build status for each package: ]) >& AS_MESSAGE_LOG_FD dnl Intialize the collection variables. SPKGS="$1" -dnl Obtain versions at configure time. -AS_IF([properties=$($SAGE_BOOTSTRAP_PYTHON build/bin/sage-package properties --format=shell $SPKGS 2>& AS_MESSAGE_LOG_FD) && eval $properties], [], [ +dnl Obtain dependencies and versions at configure time. +AS_IF([properties=$($SAGE_BOOTSTRAP_PYTHON build/bin/sage-package properties --format=shell $SPKGS 2>& AS_MESSAGE_LOG_FD) && eval $properties && dependencies=$($SAGE_BOOTSTRAP_PYTHON build/bin/sage-package dependencies --format=shell $SPKGS) && eval $dependencies], [], [ AC_MSG_ERROR([Package directory missing. Re-run bootstrap.])dnl ]) @@ -339,31 +339,14 @@ AC_DEFUN([SAGE_SPKG_FINALIZE], [dnl dnl dnl Determine package dependencies dnl - DIR=$[path_]SPKG_NAME - AS_IF([test -f "$DIR/dependencies"], [dnl - dnl - the # symbol is treated as comment which is removed - AS_VAR_SET([DEPS], [`sed 's/^ *//; s/ *#.*//; q' $DIR/dependencies`]) - ], [dnl - AS_VAR_SET([DEPS], []) - ]) - AS_IF([test -f "$DIR/dependencies_optional"], [dnl - for a in $(sed 's/^ *//; s/ *#.*//; q' "$DIR/dependencies_optional"); do - AS_VAR_APPEND([DEPS], [' $(findstring '$a',$(OPTIONAL_INSTALLED_PACKAGES)) ']) - done - ]) - AS_CASE(["$DEPS"], [*\|*], [], [AS_VAR_APPEND([DEPS], [" |"])]) - AS_IF([test -f "$DIR/dependencies_order_only"], [dnl - ADD_DEPS=$(echo $(sed 's/^ *//; s/ *#.*//; q' $DIR/dependencies_order_only)) - AS_VAR_APPEND([DEPS], [" $ADD_DEPS"]) - ], [dnl - m4_case(SPKG_SOURCE, [pip], [AS_VAR_APPEND([DEPS], [' pip'])], [:])dnl - ]) - AS_IF([test -f "$DIR/dependencies_check"], [dnl - ADD_DEPS=$(echo $(sed 's/^ *//; s/ *#.*//; q' $DIR/dependencies_check)) - AS_VAR_APPEND([DEPS], [' $(and $(filter-out no,$(SAGE_CHECK_]SPKG_NAME[)), '"$ADD_DEPS"')'])dnl - ]) - dnl - SAGE_PACKAGE_DEPENDENCIES="${SAGE_PACKAGE_DEPENDENCIES}$(printf '\ndeps_')SPKG_NAME = ${DEPS}" + AS_VAR_COPY([BUILD_DEPS], [build_deps_]SPKG_NAME) + for a in [$optional_deps_]SPKG_NAME; do + AS_VAR_APPEND([BUILD_DEPS], [' $(optional_inst_'$a') ']) + done + AS_VAR_APPEND([BUILD_DEPS], [" | $order_only_deps_]SPKG_NAME["]) + AS_VAR_COPY([DEPS], [runtime_deps_]SPKG_NAME) + AS_VAR_COPY([CHECK_DEPS], [check_deps_]SPKG_NAME) + SAGE_PACKAGE_DEPENDENCIES="${SAGE_PACKAGE_DEPENDENCIES}$(printf '\nbuild_deps_')SPKG_NAME = ${BUILD_DEPS}$(printf '\ndeps_')SPKG_NAME = ${DEPS}$(printf '\ncheck_deps_')SPKG_NAME = ${CHECK_DEPS}" dnl dnl Determine package build rules m4_case(SPKG_SOURCE, diff --git a/tox.ini b/tox.ini index 654e221aa07..185d974d8b0 100644 --- a/tox.ini +++ b/tox.ini @@ -193,9 +193,9 @@ setenv = maximal: IGNORE_MISSING_SYSTEM_PACKAGES=yes # What system packages should be installed. Default: All standard packages with spkg-configure. SAGE_PACKAGE_LIST_ARGS=--has-file=spkg-configure.m4 :standard: - recommended: EXTRA_SAGE_PACKAGES_3=_recommended $(head -n 1 build/pkgs/_recommended/dependencies) + recommended: EXTRA_SAGE_PACKAGES_3=$(sage-package list --include-dependencies _recommended) incremental: EXTRA_SAGE_PACKAGES_4=git - develop: EXTRA_SAGE_PACKAGES_4=_develop $(head -n 1 build/pkgs/_develop/dependencies) + develop: EXTRA_SAGE_PACKAGES_4=$(sage-package list --include-dependencies _develop) minimal: SAGE_PACKAGE_LIST_ARGS=_prereq maximal: SAGE_PACKAGE_LIST_ARGS=:standard: :optional: sitepackages: ENABLE_SYSTEM_SITE_PACKAGES=yes @@ -748,7 +748,7 @@ commands = # local-root: Assume we are root, run the system package commands # local-sudo: Use sudo to run the system package commands as root # - local-{root,sudo}: bash -c 'case "{env:SKIP_SYSTEM_PKG_INSTALL:}" in 1|y*|Y*);; *) eval $(build/bin/sage-print-system-package-command {env:SYSTEM} {env:__SUDO:} update) ;; esac' + local-{root,sudo}: bash -c 'case "{env:SKIP_SYSTEM_PKG_INSTALL:}" in 1|y*|Y*);; *) export PATH="build/bin:$PATH" && eval $(sage-print-system-package-command {env:SYSTEM} {env:__SUDO:} update) ;; esac' local-{root,sudo}: bash -c 'case "{env:SKIP_SYSTEM_PKG_INSTALL:}" in 1|y*|Y*);; *) export PATH="build/bin:$PATH" && eval $(sage-print-system-package-command {env:SYSTEM} {env:__SUDO:} --yes --no-install-recommends --spkg install $(sage-package list {env:SAGE_PACKAGE_LIST_ARGS}) {env:ALL_EXTRA_SAGE_PACKAGES}) || [ "$IGNORE_MISSING_SYSTEM_PACKAGES" = yes ] && echo "(ignoring errors)" ;; esac' # # All "local" environments @@ -759,7 +759,7 @@ commands = local: bash -c 'if [ ! -d prefix -o -L prefix ]; then rm -f prefix; ln -sf {env:PREFIX:{envdir}/local} prefix; fi' ##commands = - docker: bash -c 'BUILD_TAG={env:DOCKER_TAG:$(git describe --dirty --always)} .ci/write-dockerfile.sh {env:SYSTEM} "{env:SAGE_PACKAGE_LIST_ARGS:}" {env:WITH_SYSTEM_SPKG} {env:IGNORE_MISSING_SYSTEM_PACKAGES} "{env:ALL_EXTRA_SAGE_PACKAGES}" > {envdir}/Dockerfile' + docker: bash -c 'export PATH="build/bin:$PATH" && BUILD_TAG={env:DOCKER_TAG:$(git describe --dirty --always)} .ci/write-dockerfile.sh {env:SYSTEM} "{env:SAGE_PACKAGE_LIST_ARGS:}" {env:WITH_SYSTEM_SPKG} {env:IGNORE_MISSING_SYSTEM_PACKAGES} "{env:ALL_EXTRA_SAGE_PACKAGES}" > {envdir}/Dockerfile' # From https://hub.docker.com/r/multiarch/ubuntu-core/ # configure binfmt-support on the Docker host (works locally or remotely, i.e: using boot2docker) docker-{arm64,armhf}: docker run --rm --privileged multiarch/qemu-user-static:register --reset