Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions .github/workflows/python_wheels_variants.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,30 @@ jobs:
*.whl
- name: Audit wheel
run: |
set -euo pipefail
WHEEL_TAG=manylinux_2_28_x86_64
echo "--- Audit binary wheel to ensure it's compliant with ${WHEEL_TAG} standard"
auditwheel repair --only-plat --plat ${WHEEL_TAG} python-package/dist/*.whl
python3 -m wheel tags --python-tag py3 --abi-tag none --platform ${WHEEL_TAG} --remove \
wheelhouse/*.whl
mv -v wheelhouse/*.whl python-package/dist/
raw_wheels=(python-package/dist/*.whl)
if [[ ${#raw_wheels[@]} -ne 1 || ! -f "${raw_wheels[0]}" ]]; then
echo "error: expected exactly one raw wheel in python-package/dist"
exit 1
fi
raw_wheel="${raw_wheels[0]}"
auditwheel repair --only-plat --plat ${WHEEL_TAG} "${raw_wheel}"
repaired_wheels=(wheelhouse/*.whl)
if [[ ${#repaired_wheels[@]} -ne 1 || ! -f "${repaired_wheels[0]}" ]]; then
echo "error: expected exactly one repaired wheel in wheelhouse"
exit 1
fi
python3 -m wheel tags --python-tag cp312 --abi-tag abi3 --platform ${WHEEL_TAG} --remove \
"${repaired_wheels[0]}"
tagged_wheels=(wheelhouse/*.whl)
if [[ ${#tagged_wheels[@]} -ne 1 || ! -f "${tagged_wheels[0]}" ]]; then
echo "error: expected exactly one tagged wheel in wheelhouse"
exit 1
fi
rm -v "${raw_wheel}"
mv -v "${tagged_wheels[0]}" python-package/dist/
- name: Stash files
run: |
python3 ops/pipeline/manage-artifacts.py upload \
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/python_wheels_winarm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
mkdir -p wheelhouse
pip wheel --no-deps -v . --wheel-dir wheelhouse/
$wheelFile = Get-ChildItem wheelhouse/*.whl | Select-Object -First 1 -ExpandProperty FullName
python -m wheel tags --python-tag py3 --abi-tag none --platform win_arm64 --remove $wheelFile
python -m wheel tags --python-tag cp312 --abi-tag abi3 --platform win_arm64 --remove $wheelFile

- name: Upload Python wheel xgboost
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
Expand All @@ -85,7 +85,7 @@ jobs:
cd python-package
pip wheel --no-deps -v . --wheel-dir wheelhouse/
$wheelFile = Get-ChildItem wheelhouse/*.whl | Select-Object -First 1 -ExpandProperty FullName
python -m wheel tags --python-tag py3 --abi-tag none --platform win_arm64 --remove $wheelFile
python -m wheel tags --python-tag cp312 --abi-tag abi3 --platform win_arm64 --remove $wheelFile

- name: Upload Python wheel xgboost-cpu
if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/heads/release_')
Expand Down
94 changes: 51 additions & 43 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ option(USE_NVTX "Build with cuda profiling annotations. Developers only." OFF)
set(NVTX_HEADER_DIR "" CACHE PATH "Path to the stand-alone nvtx header")
option(HIDE_CXX_SYMBOLS "Build shared library and hide all C++ symbols" OFF)
option(KEEP_BUILD_ARTIFACTS_IN_BINARY_DIR "Output build artifacts in CMake binary dir" OFF)
# When ON, suppress install() rules intended for system installs (headers,
# xgboost-config.cmake, XGBoostTargets, xgboost.pc, default lib install).
# Used by python-package/CMakeLists.txt so the Python wheel's install layout
# is fully controlled there.
option(XGBOOST_FOR_PYTHON_WHEEL
"Building libxgboost embedded inside the Python wheel; skip default installs" OFF)
## CUDA
option(USE_CUDA "Build with GPU acceleration" OFF)
option(USE_NCCL "Build with NCCL to enable distributed GPU support." OFF)
Expand Down Expand Up @@ -457,48 +463,50 @@ endif()
include(CPack)

include(GNUInstallDirs)
# Install all headers. Please note that currently the C++ headers does not form an "API".
install(DIRECTORY ${xgboost_SOURCE_DIR}/include/xgboost
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# Install libraries. If `xgboost` is a static lib, specify `objxgboost` also, to avoid the
# following error:
#
# > install(EXPORT ...) includes target "xgboost" which requires target "objxgboost" that is not
# > in any export set.
#
# https://github.com/dmlc/xgboost/issues/6085
if(BUILD_STATIC_LIB)
set(INSTALL_TARGETS xgboost objxgboost dmlc)
else()
set(INSTALL_TARGETS xgboost)
endif()

install(TARGETS ${INSTALL_TARGETS}
EXPORT XGBoostTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${LIBLEGACY_INCLUDE_DIRS})
install(EXPORT XGBoostTargets
FILE XGBoostTargets.cmake
NAMESPACE xgboost::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xgboost)

include(CMakePackageConfigHelpers)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/cmake/xgboost-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake/xgboost-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xgboost)
write_basic_package_version_file(
${CMAKE_BINARY_DIR}/cmake/xgboost-config-version.cmake
VERSION ${XGBOOST_VERSION}
COMPATIBILITY AnyNewerVersion)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/cmake/xgboost-config.cmake
${CMAKE_BINARY_DIR}/cmake/xgboost-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xgboost)
if(NOT XGBOOST_FOR_PYTHON_WHEEL)
# Install all headers. Please note that currently the C++ headers does not form an "API".
install(DIRECTORY ${xgboost_SOURCE_DIR}/include/xgboost
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# Install libraries. If `xgboost` is a static lib, specify `objxgboost` also, to avoid the
# following error:
#
# > install(EXPORT ...) includes target "xgboost" which requires target "objxgboost" that is not
# > in any export set.
#
# https://github.com/dmlc/xgboost/issues/6085
if(BUILD_STATIC_LIB)
set(INSTALL_TARGETS xgboost objxgboost dmlc)
else()
set(INSTALL_TARGETS xgboost)
endif()

install(TARGETS ${INSTALL_TARGETS}
EXPORT XGBoostTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${LIBLEGACY_INCLUDE_DIRS})
install(EXPORT XGBoostTargets
FILE XGBoostTargets.cmake
NAMESPACE xgboost::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xgboost)

include(CMakePackageConfigHelpers)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/cmake/xgboost-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake/xgboost-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xgboost)
write_basic_package_version_file(
${CMAKE_BINARY_DIR}/cmake/xgboost-config-version.cmake
VERSION ${XGBOOST_VERSION}
COMPATIBILITY AnyNewerVersion)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/cmake/xgboost-config.cmake
${CMAKE_BINARY_DIR}/cmake/xgboost-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/xgboost)
endif()

#-- Test
if(GOOGLE_TEST)
Expand All @@ -519,7 +527,7 @@ if(GOOGLE_TEST)
endif()

# Add xgboost.pc
if(ADD_PKGCONFIG)
if(ADD_PKGCONFIG AND NOT XGBOOST_FOR_PYTHON_WHEEL)
configure_file(${xgboost_SOURCE_DIR}/cmake/xgboost.pc.in ${xgboost_BINARY_DIR}/xgboost.pc @ONLY)

install(
Expand Down
6 changes: 5 additions & 1 deletion cmake/Utils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ function(compute_cmake_cuda_archs archs)
elseif(CMAKE_CUDA_COMPILER_VERSION MATCHES "^([0-9]+\\.[0-9]+)")
set(CUDA_VERSION "${CMAKE_MATCH_1}")
endif()
list(SORT archs)
# NATURAL sort is needed so that 3-digit archs (100, 120) sort *after*
# 2-digit ones (70, 90). With the default STRING sort, "100" precedes "70"
# alphabetically, which caused the -virtual (PTX) entry below — applied to
# the AT -1 position — to land on the wrong architecture.
list(SORT archs COMPARE NATURAL)
unset(CMAKE_CUDA_ARCHITECTURES CACHE)
set(CMAKE_CUDA_ARCHITECTURES ${archs})

Expand Down
29 changes: 17 additions & 12 deletions doc/build.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,23 +193,28 @@ There are several ways to build and install the package from source:
$ pip install -v . # Builds the shared object automatically.

which will compile XGBoost's native (C++) code using default CMake flags. To enable
additional compilation options, pass corresponding ``--config-settings``:
additional compilation options, pass them as CMake defines through
``scikit-build-core``'s ``--config-settings``:

.. code-block:: console

$ pip install -v . --config-settings use_cuda=True --config-settings use_nccl=True
$ pip install -v . \
--config-settings cmake.define.USE_CUDA=ON \
--config-settings cmake.define.USE_NCCL=ON

Use Pip 22.1 or later to use ``--config-settings`` option.

Here are the available options for ``--config-settings``:
Common CMake options the Python wheel forwards to the libxgboost build
(see :ref:`building-the-shared-library` for the full list):

.. literalinclude:: ../python-package/packager/build_config.py
:language: python
:start-at: @dataclasses.dataclass
:end-before: def _set_config_setting(

``use_system_libxgboost`` is a special option. See Item 4 below for
detailed description.
- ``USE_CUDA`` — build with CUDA / GPU acceleration
- ``USE_NCCL`` — build with NCCL for distributed GPU training
- ``USE_DLOPEN_NCCL`` — load NCCL dynamically at runtime
- ``PLUGIN_FEDERATED`` — enable the federated learning plugin
- ``PLUGIN_RMM`` — build with RAPIDS Memory Manager support
- ``HIDE_CXX_SYMBOLS`` — hide all C++ symbols in the shared library
- ``USE_OPENMP`` — build with OpenMP (defaults to ON)
- ``XGBOOST_USE_SYSTEM_LIBXGBOOST`` — see Item 4 below

.. note:: Verbose flag recommended

Expand Down Expand Up @@ -252,12 +257,12 @@ There are several ways to build and install the package from source:
libpath = pathlib.Path(sys.base_prefix).joinpath("lib", "libxgboost.so")
assert libpath.exists()

Then pass ``use_system_libxgboost=True`` option to ``pip install``:
Then pass ``XGBOOST_USE_SYSTEM_LIBXGBOOST=ON`` to ``pip install`` as a CMake define:

.. code-block:: bash

cd python-package
pip install . --config-settings use_system_libxgboost=True
pip install . --config-settings cmake.define.XGBOOST_USE_SYSTEM_LIBXGBOOST=ON


.. note::
Expand Down
2 changes: 1 addition & 1 deletion doc/contrib/python_packaging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ completes quickly:

.. code-block:: console

$ pip install xgboost-2.0.0-py3-none-linux_x86_64.whl # Completes quickly
$ pip install xgboost-2.0.0-cp312-abi3-linux_x86_64.whl # Completes quickly

.. rubric:: Footnotes

Expand Down
1 change: 0 additions & 1 deletion ops/conda_env/python_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ dependencies:
- cloudpickle
- pytest
- hypothesis
- hatchling
- pyspark>=4.0.0
41 changes: 33 additions & 8 deletions ops/pipeline/audit-cuda-wheel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,43 @@ WHEEL_TAG=manylinux_2_28_${arch}
set -x

echo "--- Audit binary wheel to ensure it's compliant with ${WHEEL_TAG} standard"
auditwheel repair --only-plat --plat ${WHEEL_TAG} python-package/dist/*.whl
python3 -m wheel tags --python-tag py3 --abi-tag none --platform ${WHEEL_TAG} --remove \
wheelhouse/*.whl
mv -v wheelhouse/*.whl python-package/dist/
raw_wheels=(python-package/dist/*.whl)
if [[ ${#raw_wheels[@]} -ne 1 || ! -f "${raw_wheels[0]}" ]]; then
echo "error: expected exactly one raw wheel in python-package/dist"
exit 1
fi
raw_wheel="${raw_wheels[0]}"

auditwheel repair --only-plat --plat ${WHEEL_TAG} "${raw_wheel}"
repaired_wheels=(wheelhouse/*.whl)
if [[ ${#repaired_wheels[@]} -ne 1 || ! -f "${repaired_wheels[0]}" ]]; then
echo "error: expected exactly one repaired wheel in wheelhouse"
exit 1
fi
python3 -m wheel tags --python-tag cp312 --abi-tag abi3 --platform ${WHEEL_TAG} --remove \
"${repaired_wheels[0]}"
tagged_wheels=(wheelhouse/*.whl)
if [[ ${#tagged_wheels[@]} -ne 1 || ! -f "${tagged_wheels[0]}" ]]; then
echo "error: expected exactly one tagged wheel in wheelhouse"
exit 1
fi
rm -v "${raw_wheel}"
mv -v "${tagged_wheels[0]}" python-package/dist/

final_wheels=(python-package/dist/*.whl)
if [[ ${#final_wheels[@]} -ne 1 || ! -f "${final_wheels[0]}" ]]; then
echo "error: expected exactly one final wheel in python-package/dist"
exit 1
fi
final_wheel="${final_wheels[0]}"

if ! unzip -l ./python-package/dist/*.whl | grep libgomp > /dev/null; then
if ! unzip -l "${final_wheel}" | grep libgomp > /dev/null; then
echo "error: libgomp.so was not vendored in the wheel"
exit -1
fi

# Check size of wheel
pydistcheck --config python-package/pyproject.toml python-package/dist/*.whl
pydistcheck --config python-package/pyproject.toml "${final_wheel}"

# Generate meta.json only for the main CUDA variant (not cuda13)
if [[ $cuda_variant == "cuda" && $arch == "x86_64" ]]
Expand All @@ -60,7 +85,7 @@ then
# TODO(hcho3): Generate meta.json that contains both x86_64 and aarch64 wheels
echo "--- Generate meta info"
python3 ops/script/format_wheel_meta.py \
--wheel-path python-package/dist/*.whl \
--wheel-path "${final_wheel}" \
--commit-hash ${GITHUB_SHA} \
--platform-tag ${WHEEL_TAG} \
--meta-path python-package/dist/
Expand All @@ -72,7 +97,7 @@ then
python3 ops/pipeline/manage-artifacts.py upload \
--s3-bucket xgboost-nightly-builds \
--prefix ${BRANCH_NAME}/${GITHUB_SHA} --make-public \
python-package/dist/*.whl
"${final_wheel}"

if [[ $cuda_variant == "cuda" && $arch == "x86_64" ]]
then
Expand Down
2 changes: 1 addition & 1 deletion ops/pipeline/build-python-wheels-cpu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ python3 ops/docker_run.py \
--image-uri "${IMAGE_URI}" \
-- auditwheel repair --only-plat \
--plat ${WHEEL_TAG} python-package/dist/xgboost_cpu-*.whl
python3 -m wheel tags --python-tag py3 --abi-tag none --platform ${WHEEL_TAG} --remove \
python3 -m wheel tags --python-tag cp312 --abi-tag abi3 --platform ${WHEEL_TAG} --remove \
wheelhouse/xgboost_cpu-*.whl
rm -v python-package/dist/xgboost_cpu-*.whl
mv -v wheelhouse/xgboost_cpu-*.whl python-package/dist/
Expand Down
2 changes: 1 addition & 1 deletion ops/pipeline/build-win64.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ conda activate
& pip wheel --no-deps -v . --wheel-dir dist/
if ($LASTEXITCODE -ne 0) { throw "Last command failed" }

python -m wheel tags --python-tag py3 --abi-tag none `
python -m wheel tags --python-tag cp312 --abi-tag abi3 `
--platform win_amd64 --remove `
(Get-ChildItem dist/*.whl | Select-Object -Expand FullName)
if ($LASTEXITCODE -ne 0) { throw "Last command failed" }
Expand Down
5 changes: 5 additions & 0 deletions ops/pipeline/test-python-sdist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

set -euox pipefail

# Stage the C++ source tree into python-package/cpp_src/ so the sdist is
# self-contained (scikit-build-core's sdist cannot reach files above
# python-package/ by itself).
python3 ops/script/prepare_sdist.py --clean

cd python-package
python --version
python -m build --sdist
Expand Down
2 changes: 1 addition & 1 deletion ops/pipeline/test-python-with-sysprefix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ cd python-package
pip install virtualenv
virtualenv venv
source venv/bin/activate && \
pip install -v . --config-settings use_system_libxgboost=True && \
pip install -v . --config-settings cmake.define.XGBOOST_USE_SYSTEM_LIBXGBOOST=ON && \
python -c 'import xgboost'
Loading
Loading