Skip to content

Commit 794ec06

Browse files
authored
feat: add Linux aarch64/arm64 support for bioconda-utils (#866)
This PR try to add Linux aarch64/arm64 support for bioconda-utils: - Support `BASE_IMAGE` build args in `Dockerfile`: the devs can specify `BASE_IMAGE` to switch base image. - `bioconda_utils/bioconda_utils-requirements.txt`: Upgrade packages version to support Linux aarch64. - Add `--docker-base-image` image to help users specify docker base image. - Add Linux aarch64 image build to `release-please.yml` and `build-image.yml` workflow - `bioconda_utils/docker_utils.py`: create conda build subdir according to arch. After this PR, users can build the bioconda package by using same cmd with x86 by specifing `--docker-base-image` to build the package. Note that the `mulled-test` are still not supported, there are a circle dependency between `bioconda-containers` and bioconda-utils, we'd better to support bioconda-utils aarch64 image first. Related: #706 Test step: ```bash $ uname -m aarch64 # Activate a conda env conda create -n biotest conda activate biotest git clone https://github.com/Yikun/bioconda-utils.git cd bioconda-utils git checkout aarch64 # Build docker image with embed involucro for bioconda docker build -t ghcr.io/yikun/bioconda-utils-build-env-cos7-aarch64 -f Dockerfile . # Install all bioconda-utils conda install --file bioconda_utils/bioconda_utils-requirements.txt -c conda-forge -c bioconda # Install the bioconda-utils with this PR pip install -e . # Test bioconda-utils -h # Build a package to test cd bioconda-recipes bioconda-utils build --docker --packages bamstats --docker-base-image ghcr.io/yikun/bioconda-utils-build-env-cos7-aarch64 --force ``` --------- Signed-off-by: Yikun Jiang <yikunkero@gmail.com>
1 parent 1923d24 commit 794ec06

File tree

7 files changed

+72
-16
lines changed

7 files changed

+72
-16
lines changed

.github/workflows/build-image.yml

+18-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ jobs:
1414
build:
1515
name: Build image
1616
runs-on: ubuntu-20.04
17-
17+
strategy:
18+
matrix:
19+
include:
20+
- arch: arm64
21+
image: bioconda-utils-build-env-cos7-aarch64
22+
base_image: quay.io/condaforge/linux-anvil-aarch64
23+
- arch: amd64
24+
image: bioconda-utils-build-env-cos7
25+
base_image: quay.io/condaforge/linux-anvil-cos7-x86_64
1826
steps:
1927
- uses: actions/checkout@v3
2028
with:
@@ -28,11 +36,19 @@ jobs:
2836
# printf %s "::set-output name=tag::${tag#v}"
2937
printf %s "tag=${tag#v}" >> $GITHUB_OUTPUT
3038
39+
- name: Install qemu dependency
40+
run: |
41+
sudo apt-get update
42+
sudo apt-get install -y qemu-user-static
43+
3144
- name: Build image
3245
id: buildah-build
3346
uses: redhat-actions/buildah-build@v2
3447
with:
35-
image: bioconda-utils-build-env-cos7
48+
image: ${{ matrix.image }}
49+
arch: ${{ matrix.arch }}
50+
build-args: |
51+
BASE_IMAGE=${{ matrix.base_image }}
3652
tags: >-
3753
latest
3854
${{ steps.get-tag.outputs.tag }}

.github/workflows/release-please.yml

+18-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ name: release-please
88
jobs:
99
release-please:
1010
runs-on: ubuntu-latest
11+
strategy:
12+
matrix:
13+
include:
14+
- arch: arm64
15+
image: bioconda-utils-build-env-cos7-aarch64
16+
base_image: quay.io/condaforge/linux-anvil-aarch64
17+
- arch: amd64
18+
image: bioconda-utils-build-env-cos7
19+
base_image: quay.io/condaforge/linux-anvil-cos7-x86_64
1120
steps:
1221

1322
- uses: GoogleCloudPlatform/release-please-action@v2
@@ -28,12 +37,20 @@ jobs:
2837
tag=${{ steps.release.outputs.tag_name }}
2938
printf %s "::set-output name=tag::${tag#v}"
3039
40+
- name: Install qemu dependency
41+
run: |
42+
sudo apt-get update
43+
sudo apt-get install -y qemu-user-static
44+
3145
- name: Build Image
3246
if: ${{ steps.release.outputs.release_created }}
3347
id: buildah-build
3448
uses: redhat-actions/buildah-build@v2
3549
with:
36-
image: bioconda-utils-build-env-cos7
50+
image: ${{ matrix.image }}
51+
arch: ${{ matrix.arch }}
52+
build-args: |
53+
BASE_IMAGE=${{ matrix.base_image }}
3754
tags: >-
3855
latest
3956
${{ steps.get-tag.outputs.tag }}

Dockerfile

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
FROM quay.io/condaforge/linux-anvil-cos7-x86_64 as base
1+
# Specify the base image to support multi-arch images, such as
2+
# - 'quay.io/condaforge/linux-anvil-aarch64' for Linux aarch64
3+
# - 'quay.io/condaforge/linux-anvil-cos7-x86_64' for Linux x86_64
4+
ARG BASE_IMAGE=quay.io/condaforge/linux-anvil-cos7-x86_64
5+
6+
FROM ${BASE_IMAGE} as base
27

38
# Copy over C.UTF-8 locale from our base image to make it consistently available during build.
49
COPY --from=quay.io/bioconda/base-glibc-busybox-bash /usr/lib/locale/C.UTF-8 /usr/lib/locale/C.UTF-8

bioconda_utils/bioconda_utils-requirements.txt

+7-7
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ boa=0.9.*
99
conda-build=3.21.8
1010
conda-verify=3.1.*
1111
argh=0.26.* # CLI
12-
colorlog=3.1.* # Logging
12+
colorlog=4.8.* # Logging
1313
tqdm>=4.26 # Progress monitor
1414
ruamel_yaml=0.15.* # Recipe YAML parsing
1515
pyaml=17.12.* # Faster YAML parser (deprecate?)
1616
networkx=2.*
17-
pandas=0.23.*
17+
pandas=1.4.*
1818
numpy=1.19.* # Avoid breaking pandas on OSX
1919
libblas=*=*openblas # Avoid large mkl package (pulled in by pandas)
2020
boltons=18.*
21-
jsonschema=2.6.* # JSON schema verification
21+
jsonschema=3.2.* # JSON schema verification
2222
simplejson # Used by bioconda bot worker (NEEDED?)
2323
pyopenssl>=22.1 # Stay compatible with cryptography
2424

@@ -28,11 +28,11 @@ conda-forge-pinning=2022.08.25.15.20.42
2828
# tools
2929
anaconda-client=1.6.* # anaconda_upload
3030
involucro=1.1.* # mulled test and container build
31-
skopeo=0.1.35 # docker upload
31+
skopeo=1.11.* # docker upload
3232
git=2.* # well - git
3333

3434
# hosters - special regex not supported by RE
35-
regex=2018.08.29
35+
regex=2022.7.9
3636

3737
# asyncio
3838
aiohttp=3.8.* # HTTP lib
@@ -51,7 +51,7 @@ gidgethub=3.0.* # githubhandler
5151
pyjwt>=2.4.0 # githubhandler (JWT signing), needs >=2.4.0, CVE-2022-29217
5252

5353
# unknown
54-
beautifulsoup4=4.6.*
54+
beautifulsoup4=4.8.*
5555
galaxy-lib>=18.9.1
5656
jinja2>=2.10.1,<3
5757
markupsafe<2.1 # markupsafe 2.1 breaks jinja2
@@ -69,4 +69,4 @@ graphviz
6969
requests=2.22.*
7070

7171
# merge handling
72-
pygithub
72+
pygithub

bioconda_utils/cli.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -426,13 +426,16 @@ def do_lint(recipe_folder, config, packages="*", cache=None, list_checks=False,
426426
than one worker, then make sure to give each a different offset!''')
427427
@arg('--keep-old-work', action='store_true', help='''Do not remove anything
428428
from environment, even after successful build and test.''')
429+
@arg('--docker-base-image', help='''Name of base image that can be used in
430+
Dockerfile template.''')
429431
@enable_logging()
430432
def build(recipe_folder, config, packages="*", git_range=None, testonly=False,
431433
force=False, docker=None, mulled_test=False, build_script_template=None,
432434
pkg_dir=None, anaconda_upload=False, mulled_upload_target=None,
433435
build_image=False, keep_image=False, lint=False, lint_exclude=None,
434436
check_channels=None, n_workers=1, worker_offset=0, keep_old_work=False,
435-
mulled_conda_image=pkg_test.MULLED_CONDA_IMAGE):
437+
mulled_conda_image=pkg_test.MULLED_CONDA_IMAGE,
438+
docker_base_image='quay.io/bioconda/bioconda-utils-build-env-cos7:{}'.format(VERSION.replace('+', '_'))):
436439
cfg = utils.load_config(config)
437440
setup = cfg.get('setup', None)
438441
if setup:
@@ -458,6 +461,7 @@ def build(recipe_folder, config, packages="*", git_range=None, testonly=False,
458461
use_host_conda_bld=use_host_conda_bld,
459462
keep_image=keep_image,
460463
build_image=build_image,
464+
docker_base_image=docker_base_image
461465
)
462466
else:
463467
docker_builder = None

bioconda_utils/docker_utils.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
import conda
6161
import conda_build
6262

63+
from conda import exports as conda_exports
64+
6365
from . import utils
6466
from . import __version__
6567

@@ -90,9 +92,10 @@
9092
#
9193
# Note that if the directory didn't exist on the host, then the staging area
9294
# will exist in the container but will be empty. Channels expect at least
93-
# a linux-64 and noarch directory within that directory, so we make sure it
94-
# exists before adding the channel.
95+
# a linux-64/linux-aarch64 and noarch directory within that directory, so we
96+
# make sure it exists before adding the channel.
9597
mkdir -p {self.container_staging}/linux-64
98+
mkdir -p {self.container_staging}/linux-aarch64
9699
mkdir -p {self.container_staging}/noarch
97100
touch {self.container_staging}/noarch/repodata.json
98101
conda config --add channels file://{self.container_staging} 2> >(
@@ -442,8 +445,9 @@ def build_recipe(self, recipe_dir, build_args, env, noarch=False):
442445

443446
# Write build script to tempfile
444447
build_dir = os.path.realpath(tempfile.mkdtemp())
448+
# conda_exports.subdir is {platform}-{arch} like: 'linux-64' 'linux-aarch64'
445449
script = self.build_script_template.format(
446-
self=self, arch='noarch' if noarch else 'linux-64')
450+
self=self, arch='noarch' if noarch else conda_exports.subdir)
447451
with open(os.path.join(build_dir, 'build_script.bash'), 'w') as fout:
448452
fout.write(script)
449453
build_script = fout.name

bioconda_utils/utils.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949

5050
from conda_build import api
5151
from conda.exports import VersionOrder
52+
from conda.exports import subdir as conda_subdir
5253
from boa.cli.mambabuild import prepare as insert_mambabuild
5354

5455
from jsonschema import validate
@@ -1116,7 +1117,16 @@ def _filter_existing_packages(metas, check_channels):
11161117
new_metas.append(meta)
11171118
else:
11181119
existing_metas.append(meta)
1119-
for divergent_build in (existing_pkg_builds - set(build_meta.keys())):
1120+
# Filter the existing_pkg_builds according to the native CPU architecture to avoid
1121+
# inaccurate divergent build results.
1122+
#
1123+
# For example, when a package has only `linux-64` arch type package, if we
1124+
# build on aarch64 machine, the `divergent_builds` will wrongly include the linux-64
1125+
# one, we need to filter the non-native CPU architecture versions.
1126+
native_pkg_builds = {
1127+
x for x in existing_pkg_builds if x.subdir in (conda_subdir, 'noarch')
1128+
}
1129+
for divergent_build in (native_pkg_builds - set(build_meta.keys())):
11201130
divergent_builds.add(
11211131
'-'.join((pkg_key[0], pkg_key[1], divergent_build[1])))
11221132
return new_metas, existing_metas, divergent_builds

0 commit comments

Comments
 (0)