Skip to content

Commit 690c991

Browse files
authored
[backport] Build xgboost-cpu for manylinux_2_28_x86_64 (dmlc#11406) (dmlc#11407)
1 parent 052f6df commit 690c991

12 files changed

+170
-96
lines changed

.github/workflows/main.yml

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,6 @@ jobs:
3636
--prefix cache/${{ github.run_id }}/build-cpu \
3737
./xgboost
3838
39-
build-cpu-arm64:
40-
name: Build CPU ARM64 + manylinux_2_28_aarch64 wheel
41-
runs-on:
42-
- runs-on=${{ github.run_id }}
43-
- runner=linux-arm64-cpu
44-
- tag=build-cpu-arm64
45-
steps:
46-
# Restart Docker daemon so that it recognizes the ephemeral disks
47-
- run: sudo systemctl restart docker
48-
- uses: actions/checkout@v4
49-
with:
50-
submodules: "true"
51-
- name: Log into Docker registry (AWS ECR)
52-
run: bash ops/pipeline/login-docker-registry.sh
53-
- run: bash ops/pipeline/build-cpu-arm64.sh
54-
- name: Stash files
55-
run: |
56-
python3 ops/pipeline/manage-artifacts.py upload \
57-
--s3-bucket ${{ env.RUNS_ON_S3_BUCKET_CACHE }} \
58-
--prefix cache/${{ github.run_id }}/build-cpu-arm64 \
59-
./xgboost python-package/dist/*.whl
60-
6139
build-cuda:
6240
name: Build CUDA + manylinux_2_28_x86_64 wheel
6341
runs-on:
@@ -122,13 +100,35 @@ jobs:
122100
bash ops/pipeline/build-cuda.sh \
123101
xgb-ci.gpu_build_rockylinux8_dev_ver enable-rmm
124102
125-
build-manylinux2014:
103+
build-python-wheels-arm64:
104+
name: Build manylinux_2_28_aarch64 wheel
105+
runs-on:
106+
- runs-on=${{ github.run_id }}
107+
- runner=linux-arm64-cpu
108+
- tag=build-python-wheels-arm64
109+
steps:
110+
# Restart Docker daemon so that it recognizes the ephemeral disks
111+
- run: sudo systemctl restart docker
112+
- uses: actions/checkout@v4
113+
with:
114+
submodules: "true"
115+
- name: Log into Docker registry (AWS ECR)
116+
run: bash ops/pipeline/login-docker-registry.sh
117+
- run: bash ops/pipeline/build-python-wheels-arm64.sh
118+
- name: Stash files
119+
run: |
120+
python3 ops/pipeline/manage-artifacts.py upload \
121+
--s3-bucket ${{ env.RUNS_ON_S3_BUCKET_CACHE }} \
122+
--prefix cache/${{ github.run_id }}/build-python-wheels-arm64 \
123+
./xgboost python-package/dist/*.whl
124+
125+
build-python-wheels-manylinux2014:
126126
name: Build manylinux2014_${{ matrix.arch }} wheel
127127
runs-on:
128128
- runs-on
129129
- runner=${{ matrix.runner }}
130130
- run-id=${{ github.run_id }}
131-
- tag=main-build-manylinux2014-${{ matrix.arch }}
131+
- tag=main-build-python-wheels-manylinux2014-${{ matrix.arch }}
132132
strategy:
133133
fail-fast: false
134134
matrix:
@@ -145,7 +145,42 @@ jobs:
145145
submodules: "true"
146146
- name: Log into Docker registry (AWS ECR)
147147
run: bash ops/pipeline/login-docker-registry.sh
148-
- run: bash ops/pipeline/build-manylinux2014.sh ${{ matrix.arch }}
148+
- run: bash ops/pipeline/build-python-wheels-manylinux2014.sh ${{ matrix.arch }}
149+
150+
build-python-wheels-cpu:
151+
name: Build CPU wheel for ${{ matrix.manylinux_target }}_${{ matrix.arch }}
152+
runs-on:
153+
- runs-on
154+
- runner=${{ matrix.runner }}
155+
- run-id=${{ github.run_id }}
156+
- tag=main-build-python-wheels-cpu-${{ matrix.manylinux_target }}-${{ matrix.arch }}
157+
strategy:
158+
fail-fast: false
159+
matrix:
160+
include:
161+
- manylinux_target: manylinux2014
162+
arch: aarch64
163+
runner: linux-arm64-cpu
164+
- manylinux_target: manylinux2014
165+
arch: x86_64
166+
runner: linux-amd64-cpu
167+
- manylinux_target: manylinux_2_28
168+
arch: aarch64
169+
runner: linux-arm64-cpu
170+
- manylinux_target: manylinux_2_28
171+
arch: x86_64
172+
runner: linux-amd64-cpu
173+
steps:
174+
# Restart Docker daemon so that it recognizes the ephemeral disks
175+
- run: sudo systemctl restart docker
176+
- uses: actions/checkout@v4
177+
with:
178+
submodules: "true"
179+
- name: Log into Docker registry (AWS ECR)
180+
run: bash ops/pipeline/login-docker-registry.sh
181+
- run: |
182+
bash ops/pipeline/build-python-wheels-cpu.sh \
183+
${{ matrix.manylinux_target }} ${{ matrix.arch }}
149184
150185
build-gpu-rpkg:
151186
name: Build GPU-enabled R package
@@ -163,7 +198,6 @@ jobs:
163198
run: bash ops/pipeline/login-docker-registry.sh
164199
- run: bash ops/pipeline/build-gpu-rpkg.sh
165200

166-
167201
test-cpp-gpu:
168202
name: >-
169203
Run Google Tests with GPUs
@@ -208,7 +242,7 @@ jobs:
208242

209243
test-python-wheel:
210244
name: Run Python tests (${{ matrix.description }})
211-
needs: [build-cuda, build-cpu-arm64]
245+
needs: [build-cuda, build-python-wheels-arm64]
212246
runs-on:
213247
- runs-on
214248
- runner=${{ matrix.runner }}
@@ -238,7 +272,7 @@ jobs:
238272
image_repo: xgb-ci.aarch64
239273
suite: cpu-arm64
240274
runner: linux-arm64-cpu
241-
artifact_from: build-cpu-arm64
275+
artifact_from: build-python-wheels-arm64
242276
steps:
243277
# Restart Docker daemon so that it recognizes the ephemeral disks
244278
- run: sudo systemctl restart docker

ops/pipeline/build-cpu-arm64.sh renamed to ops/pipeline/build-python-wheels-arm64.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
## Build and test XGBoost with ARM64 CPU
2+
## Build and test XGBoost with ARM64 CPU (no GPU, no federated learning)
33

44
set -euo pipefail
55

@@ -14,13 +14,15 @@ source ops/pipeline/get-docker-registry-details.sh
1414
source ops/pipeline/get-image-tag.sh
1515

1616
WHEEL_TAG=manylinux_2_28_aarch64
17-
IMAGE_URI=${DOCKER_REGISTRY_URL}/xgb-ci.aarch64:${IMAGE_TAG}
17+
IMAGE_URI=${DOCKER_REGISTRY_URL}/xgb-ci.${WHEEL_TAG}:${IMAGE_TAG}
1818

1919
echo "--- Build CPU code targeting ARM64"
2020
set -x
21+
22+
python3 ops/script/pypi_variants.py --use-cpu-suffix=0 --require-nccl-dep=0
2123
python3 ops/docker_run.py \
2224
--image-uri ${IMAGE_URI} \
23-
-- ops/pipeline/build-cpu-arm64-impl.sh
25+
-- ops/pipeline/build-python-wheels-arm64-impl.sh
2426

2527
echo "--- Audit binary wheel to ensure it's compliant with ${WHEEL_TAG} standard"
2628
python3 ops/docker_run.py \
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/bash
2+
# Build Python wheels, CPU variant (no federated learning)
3+
4+
set -euo pipefail
5+
6+
if [[ -z "${GITHUB_SHA:-}" ]]
7+
then
8+
echo "Make sure to set environment variable GITHUB_SHA"
9+
exit 1
10+
fi
11+
12+
if [[ "$#" -lt 2 ]]
13+
then
14+
echo "Usage: $0 {manylinux2014,manylinux_2_28} {x86_64,aarch64}"
15+
exit 1
16+
fi
17+
18+
manylinux_target="$1"
19+
arch="$2"
20+
21+
source ops/pipeline/classify-git-branch.sh
22+
source ops/pipeline/get-docker-registry-details.sh
23+
source ops/pipeline/get-image-tag.sh
24+
25+
WHEEL_TAG="${manylinux_target}_${arch}"
26+
IMAGE_REPO="xgb-ci.${WHEEL_TAG}"
27+
IMAGE_URI="${DOCKER_REGISTRY_URL}/${IMAGE_REPO}:${IMAGE_TAG}"
28+
PYTHON_BIN="/opt/python/cp310-cp310/bin/python"
29+
30+
echo "--- Build binary wheel for ${WHEEL_TAG} (CPU only)"
31+
set -x
32+
33+
# Patch to rename pkg to xgboost-cpu
34+
python3 ops/script/pypi_variants.py --use-cpu-suffix=1 --require-nccl-dep=0
35+
python3 ops/docker_run.py \
36+
--image-uri "${IMAGE_URI}" \
37+
-- bash -c \
38+
"cd python-package && ${PYTHON_BIN} -m pip wheel --no-deps -v . --wheel-dir dist/"
39+
40+
python3 ops/docker_run.py \
41+
--image-uri "${IMAGE_URI}" \
42+
-- auditwheel repair --only-plat \
43+
--plat ${WHEEL_TAG} python-package/dist/xgboost_cpu-*.whl
44+
python3 -m wheel tags --python-tag py3 --abi-tag none --platform ${WHEEL_TAG} --remove \
45+
wheelhouse/xgboost_cpu-*.whl
46+
rm -v python-package/dist/xgboost_cpu-*.whl
47+
mv -v wheelhouse/xgboost_cpu-*.whl python-package/dist/
48+
49+
if ! unzip -l ./python-package/dist/*.whl | grep libgomp > /dev/null; then
50+
echo "error: libgomp.so was not vendored in the wheel"
51+
exit -1
52+
fi
53+
54+
# Check size of wheel
55+
pydistcheck --config python-package/pyproject.toml python-package/dist/*.whl
56+
57+
if [[ ($is_pull_request == 0) && ($is_release_branch == 1) ]]
58+
then
59+
python3 ops/pipeline/manage-artifacts.py upload \
60+
--s3-bucket xgboost-nightly-builds \
61+
--prefix ${BRANCH_NAME}/${GITHUB_SHA} --make-public \
62+
python-package/dist/*.whl
63+
fi

ops/pipeline/build-python-wheels-macos.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/bin/bash
2+
# Build Python wheels targeting MacOS (no federated learning)
23

34
set -euox pipefail
45

ops/pipeline/build-manylinux2014.sh renamed to ops/pipeline/build-python-wheels-manylinux2014.sh

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/bin/bash
2+
# Build Python wheels targeting manylinux2014 (no GPU, no federated learning)
23

34
set -euo pipefail
45

@@ -28,13 +29,11 @@ PYTHON_BIN="/opt/python/cp310-cp310/bin/python"
2829
echo "--- Build binary wheel for ${WHEEL_TAG}"
2930
set -x
3031

31-
python3 ops/script/pypi_variants.py --variant=manylinux2014
32+
python3 ops/script/pypi_variants.py --use-cpu-suffix=0 --require-nccl-dep=0
3233
python3 ops/docker_run.py \
3334
--image-uri "${IMAGE_URI}" \
3435
-- bash -c \
3536
"cd python-package && ${PYTHON_BIN} -m pip wheel --no-deps -v . --wheel-dir dist/"
36-
# discard the patch
37-
python3 ops/script/pypi_variants.py --variant=default
3837

3938
python3 ops/docker_run.py \
4039
--image-uri "${IMAGE_URI}" \
@@ -46,25 +45,6 @@ rm -rf python-package/dist/
4645
mkdir python-package/dist/
4746
mv -v wheelhouse/*.whl python-package/dist/
4847

49-
echo "--- Build binary wheel for ${WHEEL_TAG} (CPU only)"
50-
# Patch to rename pkg to xgboost-cpu
51-
python3 ops/script/pypi_variants.py --variant=cpu
52-
python3 ops/docker_run.py \
53-
--image-uri "${IMAGE_URI}" \
54-
-- bash -c \
55-
"cd python-package && ${PYTHON_BIN} -m pip wheel --no-deps -v . --wheel-dir dist/"
56-
# discard the patch
57-
python3 ops/script/pypi_variants.py --variant=default
58-
59-
python3 ops/docker_run.py \
60-
--image-uri "${IMAGE_URI}" \
61-
-- auditwheel repair --only-plat \
62-
--plat ${WHEEL_TAG} python-package/dist/xgboost_cpu-*.whl
63-
python3 -m wheel tags --python-tag py3 --abi-tag none --platform ${WHEEL_TAG} --remove \
64-
wheelhouse/xgboost_cpu-*.whl
65-
rm -v python-package/dist/xgboost_cpu-*.whl
66-
mv -v wheelhouse/xgboost_cpu-*.whl python-package/dist/
67-
6848
if [[ ($is_pull_request == 0) && ($is_release_branch == 1) ]]
6949
then
7050
python3 ops/pipeline/manage-artifacts.py upload \

ops/pipeline/build-win64-cpu.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Write-Host "--- Build binary wheel"
1818
cd ..
1919
# Patch to rename pkg to xgboost-cpu
2020
conda activate
21-
python ops/script/pypi_variants.py --variant=cpu
21+
python ops/script/pypi_variants.py --use-cpu-suffix=1 --require-nccl-dep=0
2222
if ($LASTEXITCODE -ne 0) { throw "Last command failed" }
2323

2424
cd python-package

ops/script/change_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def pypkg(
6161
with open(pyprj_path, "w") as fd:
6262
fd.write(pyprj)
6363

64-
make_pyproject("default")
64+
make_pyproject(use_cpu_suffix=0, require_nccl_dep=1)
6565

6666

6767
@cd(R_PACKAGE)

ops/script/pypi_variants.py

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@
33
import argparse
44
import os
55

6-
from test_utils import PY_PACKAGE, ROOT
6+
from test_utils import PY_PACKAGE
77

88
IN_PATH = os.path.join(PY_PACKAGE, "pyproject.toml.in")
99
OUT_PATH = os.path.join(PY_PACKAGE, "pyproject.toml")
1010

11-
WHL_CPU = """
12-
[tool.hatch.build.targets.wheel]
13-
packages = ["xgboost/"]
14-
"""
11+
NCCL_WHL = """ \"nvidia-nccl-cu12 ; platform_system == 'Linux' and platform_machine != 'aarch64'\","""
1512

16-
CHOICES = ["default", "cpu", "manylinux2014"]
13+
NAME = "{{ name }}"
14+
NCCL = "{{ nccl }}"
1715

1816

1917
def copyfile(src: str, dst: str) -> None:
@@ -23,39 +21,22 @@ def copyfile(src: str, dst: str) -> None:
2321
fd.write(content)
2422

2523

26-
def make_pyproject(variant: str) -> None:
27-
assert variant in CHOICES
24+
def make_pyproject(*, use_cpu_suffix: int, require_nccl_dep: int) -> None:
25+
if use_cpu_suffix == 1 and require_nccl_dep == 1:
26+
raise ValueError(
27+
"xgboost-cpu cannot require NCCL dependency. "
28+
"If --use-cpu-suffix=1, you must set --require-nccl-dep=0."
29+
)
2830

2931
with open(IN_PATH) as fd:
3032
pyproject = fd.read()
3133

3234
readme_dft = os.path.join(PY_PACKAGE, "README.dft.rst")
3335
readme_cpu = os.path.join(PY_PACKAGE, "README.cpu.rst")
3436
readme = os.path.join(PY_PACKAGE, "README.rst")
35-
if variant == "cpu":
36-
pyproject = (
37-
pyproject.replace("{{ name }}", "xgboost-cpu")
38-
.replace("{{ wheel }}", WHL_CPU)
39-
.replace("{{ nccl }}", "")
40-
)
41-
copyfile(readme_cpu, readme)
42-
elif variant == "manylinux2014":
43-
pyproject = (
44-
pyproject.replace("{{ name }}", "xgboost")
45-
.replace("{{ wheel }}", "")
46-
.replace("{{ nccl }}", "")
47-
)
48-
copyfile(readme_dft, readme)
49-
else:
50-
pyproject = (
51-
pyproject.replace("{{ name }}", "xgboost")
52-
.replace("{{ wheel }}", "")
53-
.replace(
54-
"{{ nccl }}",
55-
""" \"nvidia-nccl-cu12 ; platform_system == 'Linux' and platform_machine != 'aarch64'\",""",
56-
)
57-
)
58-
copyfile(readme_dft, readme)
37+
pyproject = pyproject.replace(NAME, "xgboost-cpu" if use_cpu_suffix else "xgboost")
38+
copyfile(readme_cpu if use_cpu_suffix else readme_dft, readme)
39+
pyproject = pyproject.replace(NCCL, NCCL_WHL if require_nccl_dep else "")
5940
pyproject = (
6041
f"# Generated by `{os.path.basename(__file__)}`, don't edit.\n" + pyproject
6142
)
@@ -67,10 +48,21 @@ def make_pyproject(variant: str) -> None:
6748
if __name__ == "__main__":
6849
parser = argparse.ArgumentParser()
6950
parser.add_argument(
70-
"--variant",
71-
type=str,
72-
choices=CHOICES,
73-
default="default",
51+
"--use-cpu-suffix",
52+
type=int,
53+
choices=[0, 1],
54+
required=True,
55+
help="Whether to rename the package name to xgboost-cpu",
56+
)
57+
parser.add_argument(
58+
"--require-nccl-dep",
59+
type=int,
60+
choices=[0, 1],
61+
required=True,
62+
help="Whether to require the NCCL dependency",
7463
)
7564
args = parser.parse_args()
76-
make_pyproject(args.variant)
65+
make_pyproject(
66+
use_cpu_suffix=args.use_cpu_suffix,
67+
require_nccl_dep=args.require_nccl_dep,
68+
)

0 commit comments

Comments
 (0)