From 19693a8c914174692e01d65434b386b522cebde7 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:31:22 +0000 Subject: [PATCH] depends: Update Qt to 6.8.3 --- depends/packages/native_qt.mk | 5 + depends/packages/qt.mk | 26 ++-- depends/packages/qt_details.mk | 14 +-- depends/patches/qt/cocoa_compat.patch | 23 ++++ depends/patches/qt/qtbase_avoid_qmain.patch | 2 +- depends/patches/qt/qtbase_plugins_cocoa.patch | 2 +- .../qt/qtbase_plugins_windows11style.patch | 113 ------------------ depends/patches/qt/qtbase_skip_tools.patch | 9 +- depends/patches/qt/static_fixes.patch | 12 +- 9 files changed, 62 insertions(+), 144 deletions(-) create mode 100644 depends/patches/qt/cocoa_compat.patch delete mode 100644 depends/patches/qt/qtbase_plugins_windows11style.patch diff --git a/depends/packages/native_qt.mk b/depends/packages/native_qt.mk index 3428a1ff190..5199af75212 100644 --- a/depends/packages/native_qt.mk +++ b/depends/packages/native_qt.mk @@ -96,6 +96,11 @@ $(package)_cmake_opts := -DCMAKE_EXE_LINKER_FLAGS="$$(build_LDFLAGS)" ifneq ($(V),) $(package)_cmake_opts += --log-level=STATUS endif + +ifeq ($(host_os),darwin) +$(package)_cmake_opts += -DQT_INTERNAL_XCODE_VERSION=$(XCODE_VERSION) +$(package)_cmake_opts += -DQT_NO_APPLE_SDK_MAX_VERSION_CHECK=ON +endif endef define $(package)_fetch_cmds diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 60d2b63b120..8f212c0f7cd 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -10,11 +10,11 @@ endif $(package)_linux_dependencies := freetype fontconfig libxcb libxkbcommon libxcb_util libxcb_util_cursor libxcb_util_render libxcb_util_keysyms libxcb_util_image libxcb_util_wm $(package)_freebsd_dependencies := $($(package)_linux_dependencies) $(package)_patches_path := $(qt_details_patches_path) -$(package)_patches := dont_hardcode_pwd.patch +$(package)_patches := cocoa_compat.patch +$(package)_patches += dont_hardcode_pwd.patch $(package)_patches += qtbase_avoid_qmain.patch $(package)_patches += qtbase_platformsupport.patch $(package)_patches += qtbase_plugins_cocoa.patch -$(package)_patches += qtbase_plugins_windows11style.patch $(package)_patches += qtbase_skip_tools.patch $(package)_patches += rcc_hardcode_timestamp.patch $(package)_patches += qttools_skip_dependencies.patch @@ -93,6 +93,9 @@ $(package)_config_opts += -no-feature-image_heuristic_mask $(package)_config_opts += -no-feature-keysequenceedit $(package)_config_opts += -no-feature-lcdnumber $(package)_config_opts += -no-feature-libresolv +# Disable libstdcpp_assertions (_GLIBCXX_ASSERTIONS) to prevent embedding absolute +# C++ standard library paths into object files, which breaks reproducible builds. +$(package)_config_opts += -no-feature-libstdcpp_assertions $(package)_config_opts += -no-feature-networkdiskcache $(package)_config_opts += -no-feature-networkproxy $(package)_config_opts += -no-feature-printsupport @@ -133,11 +136,10 @@ endif $(package)_config_opts_darwin := -no-dbus $(package)_config_opts_darwin += -no-feature-printsupport -$(package)_config_opts_darwin += -no-freetype +$(package)_config_opts_darwin += -no-feature-freetype $(package)_config_opts_darwin += -no-pkg-config -$(package)_config_opts_linux := -dbus-runtime -$(package)_config_opts_linux += -fontconfig +$(package)_config_opts_linux := -fontconfig $(package)_config_opts_linux += -no-feature-process $(package)_config_opts_linux += -no-feature-xlib $(package)_config_opts_linux += -no-xcb-xlib @@ -150,7 +152,7 @@ endif $(package)_config_opts_freebsd := $$($(package)_config_opts_linux) $(package)_config_opts_mingw32 := -no-dbus -$(package)_config_opts_mingw32 += -no-freetype +$(package)_config_opts_mingw32 += -no-feature-freetype $(package)_config_opts_mingw32 += -no-pkg-config # CMake build options. @@ -161,7 +163,6 @@ $(package)_config_env_darwin += OBJCXX="$$($(package)_cxx)" $(package)_cmake_opts := -DCMAKE_PREFIX_PATH=$(host_prefix) $(package)_cmake_opts += -DQT_FEATURE_cxx20=ON -$(package)_cmake_opts += -DQT_ENABLE_CXX_EXTENSIONS=OFF ifneq ($(V),) $(package)_cmake_opts += --log-level=STATUS endif @@ -198,6 +199,11 @@ $(package)_cmake_opts += -DCMAKE_DISABLE_FIND_PACKAGE_WrapSystemDoubleConversion $(package)_cmake_opts += -DCMAKE_DISABLE_FIND_PACKAGE_WrapSystemMd4c=TRUE $(package)_cmake_opts += -DCMAKE_DISABLE_FIND_PACKAGE_WrapZSTD=TRUE endif +ifeq ($(host_os),linux) +# For some reason, the `-dbus-runtime` configure +# option does not work as expected. +$(package)_cmake_opts += -DINPUT_dbus=runtime +endif ifeq ($(host_os),darwin) $(package)_cmake_opts += -DCMAKE_INSTALL_NAME_TOOL=true $(package)_cmake_opts += -DCMAKE_FRAMEWORK_PATH=$(OSX_SDK)/System/Library/Frameworks @@ -255,14 +261,14 @@ endef endif define $(package)_preprocess_cmds + patch -p1 -i $($(package)_patch_dir)/cocoa_compat.patch && \ patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch && \ patch -p1 -i $($(package)_patch_dir)/qtbase_avoid_qmain.patch && \ patch -p1 -i $($(package)_patch_dir)/qtbase_platformsupport.patch && \ patch -p1 -i $($(package)_patch_dir)/qtbase_plugins_cocoa.patch && \ - patch -p1 -i $($(package)_patch_dir)/qtbase_plugins_windows11style.patch && \ - patch -p1 -i $($(package)_patch_dir)/static_fixes.patch && \ patch -p1 -i $($(package)_patch_dir)/qtbase_skip_tools.patch && \ - patch -p1 -i $($(package)_patch_dir)/rcc_hardcode_timestamp.patch + patch -p1 -i $($(package)_patch_dir)/rcc_hardcode_timestamp.patch && \ + patch -p1 -i $($(package)_patch_dir)/static_fixes.patch endef ifeq ($(host),$(build)) $(package)_preprocess_cmds += && patch -p1 -i $($(package)_patch_dir)/qttools_skip_dependencies.patch diff --git a/depends/packages/qt_details.mk b/depends/packages/qt_details.mk index eeea2752104..e49ac6a2877 100644 --- a/depends/packages/qt_details.mk +++ b/depends/packages/qt_details.mk @@ -1,26 +1,26 @@ -qt_details_version := 6.7.3 -qt_details_download_path := https://download.qt.io/archive/qt/6.7/$(qt_details_version)/submodules +qt_details_version := 6.8.3 +qt_details_download_path := https://download.qt.io/archive/qt/6.8/$(qt_details_version)/submodules qt_details_suffix := everywhere-src-$(qt_details_version).tar.xz qt_details_qtbase_file_name := qtbase-$(qt_details_suffix) -qt_details_qtbase_sha256_hash := 8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 +qt_details_qtbase_sha256_hash := 56001b905601bb9023d399f3ba780d7fa940f3e4861e496a7c490331f49e0b80 qt_details_qttranslations_file_name := qttranslations-$(qt_details_suffix) -qt_details_qttranslations_sha256_hash := dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 +qt_details_qttranslations_sha256_hash := c3c61d79c3d8fe316a20b3617c64673ce5b5519b2e45535f49bee313152fa531 qt_details_qttools_file_name := qttools-$(qt_details_suffix) -qt_details_qttools_sha256_hash := f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f +qt_details_qttools_sha256_hash := 02a4e219248b94f1333df843d25763f35251c1074cdc4fb5bda67d340f8c8b3a qt_details_patches_path := $(PATCHES_PATH)/qt qt_details_top_download_path := https://raw.githubusercontent.com/qt/qt5/refs/heads/$(qt_details_version) qt_details_top_cmakelists_file_name := CMakeLists.txt qt_details_top_cmakelists_download_file := $(qt_details_top_cmakelists_file_name) -qt_details_top_cmakelists_sha256_hash := 9fb720a633c0c0a21c31fe62a34bf617726fed72480d4064f29ca5d6973d513f +qt_details_top_cmakelists_sha256_hash := 54e9a4e554da37792446dda4f52bc308407b01a34bcc3afbad58e4e0f71fac9b qt_details_top_cmake_download_path := $(qt_details_top_download_path)/cmake qt_details_top_cmake_ecmoptionaladdsubdirectory_file_name := ECMOptionalAddSubdirectory.cmake qt_details_top_cmake_ecmoptionaladdsubdirectory_download_file := $(qt_details_top_cmake_ecmoptionaladdsubdirectory_file_name) qt_details_top_cmake_ecmoptionaladdsubdirectory_sha256_hash := 97ee8bbfcb0a4bdcc6c1af77e467a1da0c5b386c42be2aa97d840247af5f6f70 qt_details_top_cmake_qttoplevelhelpers_file_name := QtTopLevelHelpers.cmake qt_details_top_cmake_qttoplevelhelpers_download_file := $(qt_details_top_cmake_qttoplevelhelpers_file_name) -qt_details_top_cmake_qttoplevelhelpers_sha256_hash := 5ac2a7159ee27b5b86d26ecff44922e7b8f319aa847b7b5766dc17932fd4a294 +qt_details_top_cmake_qttoplevelhelpers_sha256_hash := e11581b2101a6836ca991817d43d49e1f6016e4e672bbc3523eaa8b3eb3b64c2 diff --git a/depends/patches/qt/cocoa_compat.patch b/depends/patches/qt/cocoa_compat.patch new file mode 100644 index 00000000000..5a47b8215f2 --- /dev/null +++ b/depends/patches/qt/cocoa_compat.patch @@ -0,0 +1,23 @@ +Disable macOS 15 features in QCocoaCursor + +Bypasses an undefined reference to ___isPlatformVersionAtLeast +for the @available(macOS 15, *) check. + +Can be dropped once OSX_MIN_VERSION is updated to 15.0+. + +The disabled code was introduced in 4aeb27fbacfade7106b19c460deb5414143a5e53. +The referenced QTBUG-126240, in turn, refers to the NSCursor API for window +resize cursors. + + +--- a/qtbase/src/plugins/platforms/cocoa/qcocoacursor.mm ++++ b/qtbase/src/plugins/platforms/cocoa/qcocoacursor.mm +@@ -138,7 +138,7 @@ NSCursor *QCocoaCursor::convertCursor(QCursor *cursor) + case Qt::SizeHorCursor: + case Qt::SizeBDiagCursor: + case Qt::SizeFDiagCursor: { +-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(150000) ++#if 0 + if (@available(macOS 15, *)) { + auto position = [newShape]{ + switch (newShape) { diff --git a/depends/patches/qt/qtbase_avoid_qmain.patch b/depends/patches/qt/qtbase_avoid_qmain.patch index 45a54fe881e..56bf3353ac5 100644 --- a/depends/patches/qt/qtbase_avoid_qmain.patch +++ b/depends/patches/qt/qtbase_avoid_qmain.patch @@ -10,7 +10,7 @@ so we can safely disable it. --- a/qtbase/src/entrypoint/CMakeLists.txt +++ b/qtbase/src/entrypoint/CMakeLists.txt -@@ -104,8 +104,6 @@ if(WIN32) +@@ -105,8 +105,6 @@ if(WIN32) APPEND PROPERTY INTERFACE_QT_MODULE_LDFLAGS "-lmingw32" ) diff --git a/depends/patches/qt/qtbase_plugins_cocoa.patch b/depends/patches/qt/qtbase_plugins_cocoa.patch index 118a72d66e7..2b0cc5097f6 100644 --- a/depends/patches/qt/qtbase_plugins_cocoa.patch +++ b/depends/patches/qt/qtbase_plugins_cocoa.patch @@ -8,7 +8,7 @@ See: https://codereview.qt-project.org/c/qt/qtbase/+/634002 --- a/qtbase/src/plugins/platforms/cocoa/CMakeLists.txt +++ b/qtbase/src/plugins/platforms/cocoa/CMakeLists.txt -@@ -102,3 +102,10 @@ qt_internal_extend_target(QCocoaIntegrationPlugin CONDITION QT_FEATURE_sessionma +@@ -107,3 +107,10 @@ qt_internal_extend_target(QCocoaIntegrationPlugin CONDITION QT_FEATURE_sessionma SOURCES qcocoasessionmanager.cpp qcocoasessionmanager.h ) diff --git a/depends/patches/qt/qtbase_plugins_windows11style.patch b/depends/patches/qt/qtbase_plugins_windows11style.patch deleted file mode 100644 index 16d1d3ab5ae..00000000000 --- a/depends/patches/qt/qtbase_plugins_windows11style.patch +++ /dev/null @@ -1,113 +0,0 @@ -QWindows11Style: Calculate Spinbox size based on CommonStyle size -Use the calculation from Commonstyle and add the increased padding and -horizontally layouted buttons to the horizontal size hint. - -Fixes: QTBUG-130288 -Change-Id: I7932b782e7873a0178091a51379f17453eb585fd - -Upstream commits: - - Qt 6.8.1: 9107817eaceaacc968dbc767c24594566d637b8c - - Qt 6.9.0: 96d46cad43517adefa2eb7cb8819a0b2cc9241e6 - ---- a/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp -+++ b/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp -@@ -2048,39 +2048,22 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o - } - break; - #endif -+#if QT_CONFIG(spinbox) - case QStyle::CT_SpinBox: { - if (const auto *spinBoxOpt = qstyleoption_cast(option)) { - // Add button + frame widths -- int width = 0; -- -- if (const QDateTimeEdit *spinBox = qobject_cast(widget)) { -- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->minimumDateTime().toString(spinBox->displayFormat())); -- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->maximumDateTime().toString(spinBox->displayFormat())); -- width = qMax(textSizeMin.width(),textSizeMax.width()); -- } else if (const QSpinBox *spinBox = qobject_cast(widget)) { -- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->minimum())); -- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->maximum())); -- width = qMax(textSizeMin.width(),textSizeMax.width()); -- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->prefix()).width(); -- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->suffix()).width(); -- -- } else if (const QDoubleSpinBox *spinBox = qobject_cast(widget)) { -- const QSize textSizeMin = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->minimum())); -- const QSize textSizeMax = spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, QString::number(spinBox->maximum())); -- width = qMax(textSizeMin.width(),textSizeMax.width()); -- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->prefix()).width(); -- width += spinBoxOpt->fontMetrics.size(Qt::TextSingleLine, spinBox->suffix()).width(); -- } - const qreal dpi = QStyleHelper::dpi(option); - const bool hasButtons = (spinBoxOpt->buttonSymbols != QAbstractSpinBox::NoButtons); -- const int buttonWidth = hasButtons ? 2 * qRound(QStyleHelper::dpiScaled(16, dpi)) : 0; -+ const int margins = 8; -+ const int buttonWidth = hasButtons ? qRound(QStyleHelper::dpiScaled(16, dpi)) : 0; - const int frameWidth = spinBoxOpt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, - spinBoxOpt, widget) : 0; -- contentSize.setWidth(2 * 12 + width); -- contentSize += QSize(buttonWidth + 2 * frameWidth, 2 * frameWidth); -+ -+ contentSize += QSize(2 * buttonWidth + 2 * frameWidth + 2 * margins, 2 * frameWidth); - } - break; - } -+#endif - default: - contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget); - break; - - -Windows11Style: don't set minimum width for QAbstractSpinBox - -There is no need to set a minimum width for QAbstractSpinBox in -QWindows11Style::polish() as this might override the user preferences. -Also the minimum size handling is now properly done within -sizeFromContents(). - -Change-Id: Ibc1fd7a6f862fc85e3739025b9de581aa235d74c - -Upstream commits: - - Qt 6.8.3: f86da3d3f853adb1a5b823c1cc7be6db4a0265f3 - - Qt 6.9.0: b93a8dfdfe6900cb542fdc587dd2682007a6ac53 - - Qt 6.10.0: 2ec4c28470de115c16944653a5d4f6209452d56c - ---- a/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp -+++ b/qtbase/src/plugins/styles/modernwindows/qwindows11style.cpp -@@ -29,7 +29,6 @@ QT_BEGIN_NAMESPACE - - const static int topLevelRoundingRadius = 8; //Radius for toplevel items like popups for round corners - const static int secondLevelRoundingRadius = 4; //Radius for second level items like hovered menu item round corners --constexpr QLatin1StringView originalWidthProperty("_q_windows11_style_original_width"); - - enum WINUI3Color { - subtleHighlightColor, //Subtle highlight based on alpha used for hovered elements -@@ -2140,13 +2139,6 @@ void QWindows11Style::polish(QWidget* widget) - pal.setColor(QPalette::ButtonText, pal.text().color()); - pal.setColor(QPalette::BrightText, pal.text().color()); - widget->setPalette(pal); -- } else if (widget->inherits("QAbstractSpinBox")) { -- const int minWidth = 2 * 24 + 40; -- const int originalWidth = widget->size().width(); -- if (originalWidth < minWidth) { -- widget->resize(minWidth, widget->size().height()); -- widget->setProperty(originalWidthProperty.constData(), originalWidth); -- } - } else if (widget->inherits("QAbstractButton") || widget->inherits("QToolButton")) { - widget->setAutoFillBackground(false); - auto pal = widget->palette(); -@@ -2191,13 +2183,6 @@ void QWindows11Style::unpolish(QWidget *widget) - scrollarea->viewport()->setPalette(pal); - scrollarea->viewport()->setProperty("_q_original_background_palette", QVariant()); - } -- if (widget->inherits("QAbstractSpinBox")) { -- const QVariant originalWidth = widget->property(originalWidthProperty.constData()); -- if (originalWidth.isValid()) { -- widget->resize(originalWidth.toInt(), widget->size().height()); -- widget->setProperty(originalWidthProperty.constData(), QVariant()); -- } -- } - } - - /* diff --git a/depends/patches/qt/qtbase_skip_tools.patch b/depends/patches/qt/qtbase_skip_tools.patch index bbd87e8689f..eef65425d41 100644 --- a/depends/patches/qt/qtbase_skip_tools.patch +++ b/depends/patches/qt/qtbase_skip_tools.patch @@ -16,13 +16,10 @@ Skip building/installing unneeded tools: -# Depends on the global features being evaluated. -qt_internal_create_wrapper_scripts() - - add_library(Qt::GlobalConfig ALIAS GlobalConfig) - add_library(GlobalConfigPrivate INTERFACE) - ---- a/qtbase/cmake/QtBaseGlobalTargets.cmake -+++ b/qtbase/cmake/QtBaseGlobalTargets.cmake -@@ -349,12 +349,3 @@ elseif(WASM) + qt_internal_add_platform_internal_target(GlobalConfigPrivate) + target_link_libraries(GlobalConfigPrivate INTERFACE GlobalConfig) +@@ -390,12 +387,3 @@ elseif(WASM) qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt-wasmtestrunner.py" DESTINATION "${INSTALL_LIBEXECDIR}") endif() diff --git a/depends/patches/qt/static_fixes.patch b/depends/patches/qt/static_fixes.patch index f4e6e8f0a1d..1ae3f5774ac 100644 --- a/depends/patches/qt/static_fixes.patch +++ b/depends/patches/qt/static_fixes.patch @@ -4,8 +4,8 @@ Date: Sat Oct 4 01:00:25 2025 +0100 static fixes - See: https://bugreports.qt.io/browse/QTBUG-86287 - See: https://bugreports.qt.io/browse/QTBUG-137004 + See: https://qt-project.atlassian.net/browse/QTBUG-86287 + See: https://qt-project.atlassian.net/browse/QTBUG-137004 diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake index 26b9bf89633..0c546d09a8b 100644 @@ -24,7 +24,7 @@ diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake index 99c517e3581..a2e644f77d9 100644 --- a/qtbase/src/gui/configure.cmake +++ b/qtbase/src/gui/configure.cmake -@@ -80,10 +80,14 @@ if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS) +@@ -89,10 +89,14 @@ if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS) qt_find_package(XCB 0.3.9 COMPONENTS ICCCM PROVIDED_TARGETS XCB::ICCCM MODULE_NAME gui QMAKE_LIB xcb_icccm) endif() qt_add_qmake_lib_dependency(xcb_icccm xcb) @@ -40,7 +40,7 @@ index 99c517e3581..a2e644f77d9 100644 if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS) qt_find_package(XCB 0.3.9 COMPONENTS KEYSYMS PROVIDED_TARGETS XCB::KEYSYMS MODULE_NAME gui QMAKE_LIB xcb_keysyms) endif() -@@ -488,6 +492,7 @@ qt_config_compile_test(xcb_syslibs +@@ -515,6 +519,7 @@ qt_config_compile_test(xcb_syslibs LIBRARIES XCB::CURSOR XCB::ICCCM @@ -48,7 +48,7 @@ index 99c517e3581..a2e644f77d9 100644 XCB::IMAGE XCB::KEYSYMS XCB::RANDR -@@ -503,6 +508,7 @@ qt_config_compile_test(xcb_syslibs +@@ -530,6 +535,7 @@ qt_config_compile_test(xcb_syslibs "// xkb.h is using a variable called 'explicit', which is a reserved keyword in C++ #define explicit dont_use_cxx_explicit #include @@ -70,7 +70,7 @@ index e8fb442dd43..e964138115c 100644 XCB::RANDR --- a/qtbase/src/gui/configure.cmake +++ b/qtbase/src/gui/configure.cmake -@@ -504,6 +504,7 @@ qt_config_compile_test(xcb_syslibs +@@ -531,6 +531,7 @@ qt_config_compile_test(xcb_syslibs XCB::XFIXES XCB::XKB XCB::XCB